Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Ограничение количества запросов к скрипту за единицу времени (APC) / 5 сообщений из 5, страница 1 из 1
13.02.2013, 09:11
    #38148861
poiuytrewq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничение количества запросов к скрипту за единицу времени (APC)
Добрый день,

имеется задача, ограничить количество обращений к скрипту: не чаще одного запроса в 10 секунд с одного IP.
Решил использовать для этой цели APC, пример кода ниже:

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
<?php

if (extension_loaded('apc'))
{
	$ip = sprintf("%u", ip2long($_SERVER['REMOTE_ADDR']));

	if(apc_exists($ip))
	{
		// Если кеш ещё существует,
		// значит, последнее обращение
		// было менее 10 секунд назад

		die('Too early!');
	}
	else
	{
		// Сохраняем в кеше единичку на 10 секунд

		apc_store($ip, 1, 10);

		// Выполняем действие

		$logFileHandler	= fopen(pathinfo(__FILE__, PATHINFO_FILENAME).'.log', 'a');
		fputs($logFileHandler, date('Y-m-d H:i:s') . "\tlog entry\r\n");
		fclose($logFileHandler);
		
		die('Do action...');
	}
}
else
{
	die('APC not installed!');
}

?>



Заливаю скрипт на хостинг и начинаю лихорадочно обновлять страницу (не дожидаясь даже окончания выполнения скрипта), в результате получаю такой лог:

2013-02-13 11:06:54 log entry
2013-02-13 11:06:56 log entry
2013-02-13 11:07:01 log entry
2013-02-13 11:07:07 log entry
2013-02-13 11:07:11 log entry
2013-02-13 11:07:18 log entry
2013-02-13 11:07:20 log entry
2013-02-13 11:07:29 log entry
2013-02-13 11:07:29 log entry
2013-02-13 11:07:33 log entry

Как видно интервал в 10 секунд между запросами не соблюдается, пробую обновлять страницу примерно раз в секунду, каждый раз дожидаясь полного выполнения скрипта:

2013-02-13 11:09:15 log entry
2013-02-13 11:09:21 log entry
2013-02-13 11:09:32 log entry
2013-02-13 11:09:36 log entry
2013-02-13 11:09:42 log entry
2013-02-13 11:09:53 log entry

Собственно вопрос, почему такое происходит?
...
Рейтинг: 0 / 0
13.02.2013, 10:43
    #38148989
poiuytrewq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничение количества запросов к скрипту за единицу времени (APC)
Может ли кто-нибудь протестировать скрипт на своём севрере?
...
Рейтинг: 0 / 0
13.02.2013, 11:39
    #38149086
Inkelyad
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничение количества запросов к скрипту за единицу времени (APC)
poiuytrewq,

область хранения данных apc, помнится, не шарилась между различными
экземплярами php интерпретатора. (см https://bugs.php.net/bug.php?id=57825] https://bugs.php.net/bug.php?id=57825 )

Те lock переменная у этих запросов на самом деле могла быть разная.
...
Рейтинг: 0 / 0
14.02.2013, 09:49
    #38150615
poiuytrewq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничение количества запросов к скрипту за единицу времени (APC)
Понятно, пробую решить задачу на файлах

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
<?php

function remove_expired_entries($value)
{
	list($ip, $time) = explode('-', $value);
	if (time() - $time < 10) return true;
}

function clean_entries($value)
{
	list($ip, $time) = explode('-', $value);
	return $ip;
}

$file = 'access.dat';
$data = array();

if(is_readable($file))
{
	$data = array_filter(file('access.dat', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES), 'remove_expired_entries');
}

$ip = sprintf("%u", ip2long($_SERVER['REMOTE_ADDR']));

if(!in_array($ip, array_map('clean_entries', $data)))
{
	$data[] = $ip . '-' . time();
	file_put_contents($file, implode("\n", $data), LOCK_EX);

	// Do some action

	$logFileHandler	= fopen(pathinfo(__FILE__, PATHINFO_FILENAME).'.log', 'a');
	fputs($logFileHandler, date('Y-m-d H:i:s') . "\t{$ip}\r\n");
	fclose($logFileHandler);
	
	die('OK');
}

die('ERR');

?>



натравливаю на скрипт ApacheBench 1000 запросов, 100 единовременных, в лог попадает 4 записи с одинаковым временем, т.е. с момента чтения файла с данными о подключениях до момента его обновления успевают "проскочить" 4 запроса
...
Рейтинг: 0 / 0
14.02.2013, 10:38
    #38150688
poiuytrewq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничение количества запросов к скрипту за единицу времени (APC)
Выставляю эксклюзивную блокировку перед началом чтения и закрываю после записи, все вроде нормально теперь работает
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Ограничение количества запросов к скрипту за единицу времени (APC) / 5 сообщений из 5, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]