IDr
Новичок
Ограничение на выполнение одного экземпляра php-файла с одного IP
Подобные темы неоднократно поднимались но не в одной я не нашел решения своей задачи.
Есть у меня страница с несколькими рекламными блоками (от 2 до 8), рекламные блоки сделаны в <iframe> ведущими на рекламный сервер. Соответственно когда открывается страница с рекламой, начинают подгружаться <iframe>. Причем иногда (около 5% случаев) подгруздка идет одновременно (миллисекунда в миллисекунду). Получается что один скрипт не знает о выполнении второго и они могут вывести один и тот же баннер одновременно, т.к. проверка на то показан уже баннер на этой странице или нет, не работает, ведь проверка на показанность баннера в двух скриптах запускается параллельно.
Мне кажется, что наиболее рациональный вариант это создать ограничение на выполнение только одного экземпляра этого скрипта с одного IP.
Пробовал вариант с mod_limitipconn на Apache, но этот вариант не подходит, в случае исчерпания лимита он выдает «503 Service Temporarily Unavailable», а мне нужно, что бы скрипты просто становились в очередь.
-~{}~ 30.11.06 17:02:
Решил проблему следующим образом (используя MySQL):
Создал таблицу:
т.к она «ENGINE=MEMORY» работает очень быстро...
В начале скрипта написал следующий код:
В конце скрипта:
Все работает и довольно быстро.
Если есть другие варианты решения данной проблемы или вы считаете это решение плохим - прошу высказываться.
PS Заметил интересную штуку, бываю люди у которых грузятся фреймы через разные IP. То есть первый фрейм через один IP второй фрейм через другой. На 4000 показов 2 таких человека прошло.
Подобные темы неоднократно поднимались но не в одной я не нашел решения своей задачи.
Есть у меня страница с несколькими рекламными блоками (от 2 до 8), рекламные блоки сделаны в <iframe> ведущими на рекламный сервер. Соответственно когда открывается страница с рекламой, начинают подгружаться <iframe>. Причем иногда (около 5% случаев) подгруздка идет одновременно (миллисекунда в миллисекунду). Получается что один скрипт не знает о выполнении второго и они могут вывести один и тот же баннер одновременно, т.к. проверка на то показан уже баннер на этой странице или нет, не работает, ведь проверка на показанность баннера в двух скриптах запускается параллельно.
Мне кажется, что наиболее рациональный вариант это создать ограничение на выполнение только одного экземпляра этого скрипта с одного IP.
Пробовал вариант с mod_limitipconn на Apache, но этот вариант не подходит, в случае исчерпания лимита он выдает «503 Service Temporarily Unavailable», а мне нужно, что бы скрипты просто становились в очередь.
-~{}~ 30.11.06 17:02:
Решил проблему следующим образом (используя MySQL):
Создал таблицу:
Код:
CREATE TABLE `activeip_tmp` (
`active_ip` int(10) unsigned NOT NULL default '0',
`lock_time` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`active_ip`)
) ENGINE=MEMORY DEFAULT CHARSET=cp1250;
В начале скрипта написал следующий код:
PHP:
$wait_time=24; //sec.
$client_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) ) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) ) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : getenv('REMOTE_ADDR') );
$ipnum = sprintf("%u", ip2long($client_ip));
$locked=false;
for($for_start=microtime(true);(microtime(true)-$for_start)<($wait_time+5); )
{
$query_ip_test="SELECT `active_ip`, (UNIX_TIMESTAMP()-`lock_time`) as locked_sec FROM `activeip_tmp` WHERE `active_ip`=$ipnum";
$ip_ar=$GLOBALS["db"]->myquery($query_ip_test);
if (!is_array($ip_ar))
{ my_error_log(0,"Не могу выполнить запрос:\n".$query_ip_test,__FILE__,__LINE__);
die();
}
if (count($ip_ar)>0)
{
// На случай если скрипт был прерван и сам не удалил запись о блокировке
if ($ip_ar[0]["locked_sec"]>$wait_time)
{
my_error_log(0,"Принудительно снимаем блокировку $wait_time сек.:",__FILE__,__LINE__);
$del_query="DELETE FROM activeip_tmp WHERE (UNIX_TIMESTAMP()-`lock_time`) > $wait_time ";
$GLOBALS["db"]->myquery($del_query);
}
}else
{
$insert_query="INSERT
INTO activeip_tmp(`active_ip`, `lock_time`)
VALUES ('$ipnum', UNIX_TIMESTAMP())";
$result=$GLOBALS["db"]->myquery($insert_query);
if ($result>0)
{
$locked=true;
break;
}
}
usleep(50000); //0.05 cек
}
// На случай если цикл закончится по таймеру ($wait_time+5),
// может быть вызвано только ошибкой в коде или проблемой с базой.
if (!$locked)
{
my_error_log(0,"Заблокировать не удалось за ".($wait_time+5)."сек. (ошибка работы кода):",__FILE__,__LINE__);
}
В конце скрипта:
PHP:
if ($locked)
{
$del_query="DELETE FROM activeip_tmp WHERE `active_ip` = $ipnume ";
$GLOBALS["db"]->myquery($del_query);
}
Если есть другие варианты решения данной проблемы или вы считаете это решение плохим - прошу высказываться.
PS Заметил интересную штуку, бываю люди у которых грузятся фреймы через разные IP. То есть первый фрейм через один IP второй фрейм через другой. На 4000 показов 2 таких человека прошло.