ExBB Community » » PHP/Perl » Уменьшение нагрузки на хостинг средствами PHP

Страниц (1): [1]
 

1. Gori - 31 января 2015 — 11:32 - перейти к сообщению
Нашёл скриптик интересный.
Но протестить его не смогу, поэтому прошу посмотрите, насколкьо он рабочий?

Создаём таблицу в БД:

CODE:
CREATE TABLE `all_visits` (
`ip` varchar(15) DEFAULT NULL,
`date` int(11) DEFAULT NULL,
INDEX (`date` Desc)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


Дальше идёт сам скрипт, который всё делает.

CODE:
<?php
if (!empty($_SERVER['HTTP_CLIENT_IP']))
$ip=$_SERVER['HTTP_CLIENT_IP'];
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
else $ip=$_SERVER['REMOTE_ADDR'];
$bot=$_SERVER['HTTP_USER_AGENT'];

if (strstr($_SERVER['HTTP_USER_AGENT'], 'Yandex')) {$bot='Allowed_bot';}
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'Google')) {$bot='Allowed_bot';}
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'Yahoo')) {$bot='Allowed_bot';}
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'Mail.Ru')) {$bot='Allowed_bot';}
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'Bing')) {$bot='Allowed_bot';}

if ($bot!='Allowed_bot') {

$link=mysql_connect("IP-адрес-MYSQL","Login_mysql","Password_mysql") or die("Could not connect: ".mysql_error());
mysql_select_db("ИМЯ_БД", $link);

$result=mysql_query("INSERT INTO all_visits (ip,date)
VALUES ('".$ip."','".time(true)."')");
$result=mysql_query("SELECT count(1) FROM all_visits
WHERE (ip='".$ip."' and date>'".(time(true)-5)."')", $link);
$count_visit=mysql_fetch_array($result);

if ($count_visit[0]>30) {
$file_htaccess=".htaccess";
$start_line=0;

$lines=file($file_htaccess);
for ($n=0; $n<=count($lines)-1; $n++) {
$lines_htaccess[]=$lines[$n];
if ($lines[$n] == "<Limit GET POST> \r\n") {
$lines_htaccess[]=$lines[$n+1]; //order allow,deny
$start_line=$n+2;
break;
}
}

if ($start_line!=0) {
$lines_htaccess[]=" deny from ".$ip."\r\n";
for ($n=$start_line; $n<=count($lines); $n++) $lines_htaccess[]=$lines[$n];
} else {
$lines_htaccess = $lines;
$lines_htaccess[]="<Limit GET POST> \r\n";
$lines_htaccess[]=" order allow,deny \r\n";
$lines_htaccess[]=" deny from ".$ip."\r\n";
$lines_htaccess[]=" allow from all \r\n";
$lines_htaccess[]="</Limit> \r\n\r\n";
}

file_put_contents($file_htaccess, $lines_htaccess);
}
}
?>


Будет работать это?
Может быть есть проще способ?

Суть, как я понял, в том, что создаётся чёрный список IP, кто обращается чаще 30 раз за 5 секунд.
2. 1Bot - 31 января 2015 — 12:04 - перейти к сообщению
Gori
Не совсем понятно откуда должен вызываться данный скрипт?
Если при запросе любой страницы, то можно отсекать без использования средств apache.
Да и частое перезапись и большой файл .htaccess будет постоянно нагружать дисковую подсистему, что наоборот загрузит сервер, может даже более, чем при обычной отдаче контента.
(Добавление)
Для nginx уже есть нужный функционал контроля количества одновременных соединений. Не совсем то, что Вы задумали, но тоже иногда полезно.

Для защиты Web-сервера от перегрузки и попыток осуществить DoS-атаку добавьте в конфиг следующие строки:

# vi /etc/nginx/nginx.conf
CODE:
# Описываем зону (slimits), в которой будут храниться состояния сессий. Зона размером 1 Мб может хранить около 32000 состояний, мы устанавливаем ее размер равным 5 Мб
limit_zone slimits $binary_remote_addr 5m;
# Задаем максимальное количество одновременных соединений для одной сессии. По сути, это число задает максимальное количество соединений с одного IP
limit_conn slimits 5;


Первая директива должна находиться в секции HTTP, вторая – в секции location. Когда количество соединений выйдет за пределы лимитов, клиент получит сообщение "Service unavailable" с кодом 503.
3. Gori - 31 января 2015 — 12:59 - перейти к сообщению
1Bot , спасибо, у меня как раз nginx.
То что надо.
Это так и нужно без изменений прописать?

CODE:
limit_zone slimits $binary_remote_addr 5m;


Или вместо этого:
CODE:
$binary_remote_addr

нужно что-то своё прописать?

Я правильн опонял, что первую строчку нужно кинуть в файл: httpd.conf ?
А вторую в /etc/nginx/nginx.conf ?
4. 1Bot - 31 января 2015 — 19:23 - перейти к сообщению
Gori пишет:
Это так и нужно без изменений прописать?

CODE:
limit_zone slimits $binary_remote_addr 5m;

Да, так и нужно без изменений прописать. Вместо $binary_remote_addr nginx подставит IP конкретного инициатора запроса к web-серверу.
(Добавление)
Gori пишет:
Я правильно опонял, что первую строчку нужно кинуть в файл: httpd.conf ?
А вторую в /etc/nginx/nginx.conf ?

Обе строчки в файле /etc/nginx/nginx.conf в разных секциях. Пример для ограничения число одновременных закачек(соединений) для всего виртуального хоста:
CODE:
user www;
worker_processes 2;
pid /var/run/nginx.pid;

events {
use kqueue;
worker_connections 1024;
multi_accept on;
}
http {
include mime.types;
default_type application/octet-stream;
large_client_header_buffers 4 4k;
tcp_nopush on;
sendfile on;
output_buffers 32 512k;
sendfile_max_chunk 128k;
postpone_output 1460;
tcp_nodelay on;
limit_zone lconn $binary_remote_addr 5m;
fastcgi_intercept_errors on;
server_names_hash_bucket_size 64;
client_max_body_size 15m;
server {
listen IP_своего_веб_сервера;
server_name DNS_имя_своего_веб_сервера;
limit_conn lconn 5;
location / {
root /usr/local/www/папка_с_содержимым_сайта;
index index.html index.htm;
}
}
}
5. Gori - 1 февраля 2015 — 09:09 - перейти к сообщению
Так, с секцией "http" понятно и спервой строчкой.

Но на примере вторая строчка почему-то прописана в секции "server"
а в секции "location" её нет, хотя вверху вроде бы написано, что в локейшн нужно.

Как правильно?
6. Gori - 1 февраля 2015 — 09:37 - перейти к сообщению
Вроде бы нашёл ответ: http://nginx.org/ru/docs/http/ng...conn_module.html

Там кстати ещё есть дополнения с limit_conn addr 1;
7. Gori - 1 февраля 2015 — 11:56 - перейти к сообщению
Насколько вообще принципиально добавлять эти две строчки в разные секции?

Что будет если я добавлю не в http, а обе в location?

Вопрос кстати возник потому что прочитал ещё парочку статеек. Там вообще неразбериха куда что добавлять.
К тому же с новыми версиями nginx что-то реально поменялось в этом отношении.

Хостеру написал, он что-то вообще неадеватное ответил, типа всё что касается nginx - это заботы самого клиента.
8. 1Bot - 1 февраля 2015 — 13:30 - перейти к сообщению
Gori , по приведенной Вами ссылке все подробно написано
Цитата:
Директива
Синтаксис: limit_conn зона число;
Умолчание: —
Контекст: http, server, location
Задаёт зону разделяемой памяти и максимально допустимое число соединений для одного значения ключа. При превышении этого числа в ответ на запрос сервер вернёт ошибку 503 (Service Temporarily Unavailable).

Допустимо одновременное указание нескольких директив limit_conn, при этом будет срабатывать любое из ограничений.

Директивы наследуются с предыдущего уровня при условии, что на данном уровне не описаны свои директивы limit_conn.


Gori пишет:
Там кстати ещё есть дополнения с limit_conn addr 1;

addr - это имя зоны
9. Gori - 1 февраля 2015 — 13:54 - перейти к сообщению
Что-то я так ничего и не понял.

Вот я хочу прописать вот эти четыре строчки в файл конфигурации nginx:
CODE:
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn perip 100;

limit_req_zone $binary_remote_addr zone=dynamic:10m rate=2r/s;
limit_req zone=dynamic burst=10 nodelay;


Файл конфигурации такой:

CODE:
server {
.....................
location / {

....................................
}
}


Я должен вот так прописать?

CODE:
server {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_req_zone $binary_remote_addr zone=dynamic:10m rate=2r/s;

location / {
limit_conn perip 100;
limit_req zone=dynamic burst=10 nodelay;
}
}

Яндекс.Метрика   

Powered by ExBB
[Script Execution time: 0.0412]     [ ]