За последние 24 часа нас посетили 18305 программистов и 1642 робота. Сейчас ищут 1807 программистов ...

Защита от множественных запросов к сайту.

Тема в разделе "Решения, алгоритмы", создана пользователем Amperandus, 6 сен 2011.

  1. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Доброго времени суток. Нужен совет.

    Есть сайт, бд которого валиться в аут от зажатия ctrl+f5 примерно за две минуты. На хостинге защиты от подобного флуда нет, хотя и стоит freebsd админы говорят, что iptables на сервере нет.

    в логах долгих запросов нет - проверял, время обработки всех запросов 0 секунд, иногда проскакивает 1 сек.

    вот это самый долгий:

    [sql]# Query_time: 1 Lock_time: 0 Rows_sent: 6 Rows_examined: 112
    SELECT a.*
    FROM `advertisment` a
    LEFT JOIN `adv_cats` ac ON a.id = ac.adv_id
    WHERE ac.cat_id IN (0, 1)
    AND type = '5'
    ORDER BY RAND();[/sql]
    Собственно нужен совет - что делать, писать / использовать готовые решения по скриптовой блокировке такого спама (т.е. количество запросов к сайту в секунду, больше какого то - блокировать по ip) или еще какие то варианты.

    И сколько запросов в секунду с ip считается нормой? Пока просто нагуглил совет блочить, если запросов больше 10, но вдруг кто нить знает где находится более менее подробное руководство.

    Параллельно попробую еще кэширование некоторых запросов сделать.
     
  2. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Мысли в слух: то же самое на своем компе с локальным сервером пробовал сделать - никой ктрл+ф5 сайт (локальную версию) не укладывает....
     
  3. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    я себя на 3000 в секунду нормально чувствую.
     
  4. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    просто я вообще хз в какую сторону копать....

    на локальном сервере у меня не падает бд, на хостинге

    Dedicated server: (lw) Athlon 64 3000+ / 1GB / 160GB / 100mbs / 5000GB / FreeBSD 8.x 32bit / Webmin+Virtualmin

    бд валиться, хотя судя по параметрам не должна. Запросы из логов с долгим временем выполнения при ручном вводе через phpmyadmin выполняются максимум за 0.0150 с. - это самые большие, а так 0,009 - 0,020 с.
     
  5. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    как валиться-то?

    настройки БД? Тюнинг? настройки сервера и т.д.

    там много нюансов.
     
  6. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    вот кусок переписки заказчиков (я код взялся поправить) и админов сервера:

    заказчик:
    Сейчас и вовсе не открывается сайт, сначало выдало ошибку
    Warning: mysql_connect() [function.mysql-connect]: User mdova already has more than 'max_user_connections' active connections in /usr/home/mdova/public_html/classes/DataBase/Class.php on line 24
    MySQL Error! Name: NoConnection.
    MySQL answer: User mdova already has more than 'max_user_connections' active connections.

    а затем и вовсе все исчезло

    Данные не получены
    Невозможно загрузить веб-страницу, так как не поступили данные от сервера.
    Вот несколько советов и рекомендаций:
    Обновите эту страницу позже.
    Ошибка 324 (net::ERR_EMPTY_RESPONSE): Сервер разорвал соединение, не отправив данные.

    в чем проблема??? Что там случилось с сайтом?

    админ:

    Сервер упирается в диск.
    В mysql зависают запросы
    mysql> show processlist;
    +------+-------+-----------+-------+---------+------+----------------+----------------------------------------------------------------------+
    | Id | User | Host | db | Command | Time | State | Info |
    +------+-------+-----------+-------+---------+------+----------------+----------------------------------------------------------------------+
    | 6080 | mdova | localhost | mdova | Query | 43 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6081 | mdova | localhost | mdova | Query | 43 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6087 | mdova | localhost | mdova | Sleep | 29 | | NULL |
    | 6092 | root | localhost | NULL | Query | 0 | NULL | show processlist |
    | 6094 | mdova | localhost | mdova | Sleep | 25 | | NULL |
    | 6096 | mdova | localhost | mdova | Sleep | 25 | | NULL |
    | 6097 | mdova | localhost | mdova | Sleep | 25 | | NULL |
    | 6099 | mdova | localhost | mdova | Query | 31 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6100 | mdova | localhost | mdova | Sleep | 24 | | NULL |
    | 6102 | mdova | localhost | mdova | Query | 27 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6103 | mdova | localhost | mdova | Sleep | 24 | | NULL |
    | 6105 | mdova | localhost | mdova | Query | 27 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6109 | mdova | localhost | NULL | Sleep | 24 | | NULL |
    | 6110 | mdova | localhost | mdova | Query | 24 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6113 | mdova | localhost | mdova | Query | 22 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6114 | mdova | localhost | mdova | Query | 22 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6115 | mdova | localhost | mdova | Query | 22 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6116 | mdova | localhost | mdova | Query | 22 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6117 | mdova | localhost | mdova | Query | 22 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6118 | mdova | localhost | mdova | Sleep | 22 | | NULL |
    | 6119 | mdova | localhost | mdova | Query | 22 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6120 | mdova | localhost | mdova | Query | 20 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6121 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6122 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6123 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6124 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6125 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6126 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 6127 | mdova | localhost | mdova | Query | 21 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 7577 | mdova | localhost | mdova | Query | 1 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    | 7593 | mdova | localhost | mdova | Query | 1 | Writing to net | Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") |
    +------+-------+-----------+-------+---------+------+----------------+-----

    Что является причиной ошибки
    User mdova already has more than 'max_user_connections' active connections in

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

    Если с запросом Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d") сайт выдавал ошибку что максимум подключений к бд, до тех пор пока через myadmin не убьешь лишние запросы (он как ни странно работает), то сейчас где то минуту - две - три подвисает т.е. не выдает сайт пользователю, просто идет загрузка, так же как и идет загрузка пхпмайадмина, а затем начинает нормально работать. т.е. прорабатывает запросы.

    ОС - FreeBSD 8.1-RELEASE (GENERIC) #0: Mon Jul 19 02:55:53 UTC 2010

    могу выложить настройки mysql, полные или только если какие то отдельные пункты нужны
     
  7. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    теперь еще интереснее...

    404 Not Found
    nginx/1.0.5

    через ssh

    mysql> show processlist;
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    | Id | User | Host | db | Command | Time | State | Info |
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    | 64578 | root | localhost | NULL | Query | 0 | NULL | show processlist |
    | 64591 | mdova | localhost | mdova | Sleep | 0 | | NULL |
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    2 rows in set (0.00 sec)
     
  8. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    mysql> show processlist;
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    | Id | User | Host | db | Command | Time | State | Info |
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    | 64960 | root | localhost | NULL | Query | 0 | NULL | show processlist |
    | 65293 | mdova | localhost | mdova | Sleep | 0 | | NULL |
    | 65294 | mdova | localhost | mdova | Sleep | 0 | | NULL |
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    3 rows in set (0.00 sec)

    mysql> show processlist;
    +-------+-------+-----------+-------+---------+------+----------------+-------------------------------------+
    | Id | User | Host | db | Command | Time | State | Info |
    +-------+-------+-----------+-------+---------+------+----------------+-------------------------------------+
    | 64960 | root | localhost | NULL | Query | 0 | NULL | show processlist |
    | 65294 | mdova | localhost | mdova | Query | 0 | Writing to net | Select * FROM category WHERE id='1' |
    | 65295 | mdova | localhost | mdova | Sleep | 1 | | NULL |
    +-------+-------+-----------+-------+---------+------+----------------+-------------------------------------+
    3 rows in set (0.00 sec)

    mysql> show processlist;
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    | Id | User | Host | db | Command | Time | State | Info |
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    | 64960 | root | localhost | NULL | Query | 0 | NULL | show processlist |
    | 65296 | mdova | localhost | mdova | Sleep | 0 | | NULL |
    +-------+-------+-----------+-------+---------+------+-------+------------------+
    2 rows in set (0.00 sec)

    В браузере 404, в консоли такая вот картина, т.е. какие то запросы обрабатываются, только вот откуда они хз. или в очередь ставится или что.
     
  9. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    а что в логах нгинкса?
     
  10. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    индексы есть на таблицах? тип таблиц?

    на myisam на битых индексах тормозить будет жутко.

    и 20 коннектов для mysql ниочем.
     
  11. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    лучше прогоните таблицы через repair. + постройте индексы по выборкам.
     
  12. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    индексы есть, насчет битых проверю.

    в настройках скуля стояло

    wait_timeout 28800, поменяли на 30 - соединений висящих в бд нет, но сайт валится все равно, что теперь непонятно. хотя поднимается быстрее.
    max_connections стоит равным 100

    таблицы сейчас попробую прогнать.
     
  13. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    CHECK TABLE для всех таблиц выдал ОК

    в логан никса error.log только то, что не хватает нескольких изображений.
     
  14. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    поставьте в настройка mysql логирование медленных запросов и смотрите где тормоз.
     
  15. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    таблица adverts большая?

    покаж как она устроена?
     
  16. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Select * FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d")

    этот запрос я на count() уже переделал, он только получал количество объявлений за сегодня. в лог мскуля выводятся все запросы, дальше уже по времени ищу, медленных сейчас нет. Точнее вчера не было, сегодня не проверял.

    На сервере с каждым днем интереснее, то сам хостинг лежит, то апач падает из - за зависших запросов. Вчера кто то всю базу объявлений, как раз таблицу advert грохнул.

    Конкретно по таблице адверт - большая, будет еще большая, планируемая нагрузка 15 - 30к новых объявлений в день.

    CREATE TABLE `adverts` (
    `id` int(11) NOT NULL auto_increment,
    `id_category` int(11) NOT NULL,
    `title` text NOT NULL,
    `text` text NOT NULL,
    `date` varchar(20) NOT NULL,
    `price` varchar(100) default NULL,
    `curency` char(10) default NULL,
    `id_city` int(11) NOT NULL,
    `id_user` int(11) NOT NULL,
    `check` int(11) default NULL,
    `on_off` int(11) NOT NULL,
    `vip` int(11) NOT NULL,
    `color` int(11) NOT NULL,
    `look` varchar(255) default '0',
    `data_click` text NOT NULL,
    `video` text NOT NULL,
    `left` varchar(255) NOT NULL,
    `right` int(11) NOT NULL,
    `vip_date` char(10) NOT NULL,
    `foto` int(11) NOT NULL,
    `parse` int(1) NOT NULL default '0',
    `old_num` char(20) NOT NULL,
    `upkol` int(5) NOT NULL,
    `original_id` int(11) NOT NULL,
    PRIMARY KEY (`id`),
    KEY `original_id` (`original_id`),
    KEY `date` (`date`),
    KEY `vip` (`vip`),
    KEY `on_off` (`on_off`),
    KEY `id_category` (`id_category`),
    KEY `check` (`check`)
    ) ENGINE=MyISAM AUTO_INCREMENT=29823 DEFAULT CHARSET=cp1251 PACK_KEYS=0;
     
  17. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    а кто админ?
    =)
     
  18. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда

    она у тебя при поиске ВСЮ таблицу лопатит. Чем больше будет объявлений тем хуже будет. ТЫ подумай над изменнием структуры.

    это 100% жопа.

    почему у тебя unixtime как varchar(20)

    сдается мне, что при таком подходе НЕ МУДРЕНО, что у тебя там все раком встает.

    как индексы не строй по текстовым полям =) с преобразованием из текста в int и обратно в текст... ваще ипануться...

    в общем в таком состоянии БД - стоять раком - ее нормальное состояние.
     
  19. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    горе от ума.

    не надо в условии where использовать функции на поля. Так действительно будет всегда полный перебор.
    что мешает хотя бы вычислить текущую дату и писать where date='2011-11-11' ?
     
  20. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Ну во первых это все таки не совсем у меня. Меня взяли поправить запросы к бд в фильтрах объявлений, т.к. там на первом же фильтре падала бд. Ну а дальше пошло поехало.

    Проверять структуру бд как то в голову не приходило, да и заказчик на это внимания не обращал.

    в данный момент запрос вот так выглядит:

    Select count(*) as count FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d").

    У меня была мысль что надо бы поменять поля, в частности `check` int(11) default NULL, имеет всего три значения 0,1,2 и таких большинство, но решил что фиг с ним, точнее руки просто не дошли.

    Займусь тогда изменением структуры, только как бы весь сайт тогда не грохнулся.
     
  21. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Кто админит я хз. Хостинг заказчики брали до меня. Сейчас кстати админы сказали что обновили днс и вместо сайта красуется

    Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (61)

    Всего навсего на сервер хостера идет ддос атака. Это админы отписали.

    Кстати заказчик интересуется где можно взять нормальный хостинг с каналом в 1 гб и сколько это будет стоить, никто не в курсе?
     
  22. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    При правке типов полей перестает работать выборка по объявлениям...

    Вопрос: в чем разница между

    [sql]Select count(*) as count FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d"). [/sql]

    и

    PHP:
    1. <?php
    2. $stTime = mktime(0, 0, 0, date("m")  , date("d"), date("Y"));
    3. $endTime = mktime(23, 59, 59, date("m")  , date("d"), date("Y"));
    4. $f = mysql_query('Select count(*) as count FROM adverts WHERE `date` between '.$stTime.' and '.$endTime.'');
    5. ?>
     
  23. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    поменять тип date на int(11). он же строковый сейчас и between не покатит.

    date >= $st and date <= $en
     
  24. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    мы арендуем 3 сервера на 1Г в разных конторах. 1Г честный. Проверяли. в пн. спрошу у админов конторы и стоимость.
     
  25. Amperandus

    Amperandus Активный пользователь

    С нами с:
    13 мар 2009
    Сообщения:
    226
    Симпатии:
    11
    Уже не требуется. Во всяком случае пока.

    1. Убрал обращение к сайту погоды при каждом открытии сайта.
    2. Заказчик на 5 минут заказал ддос сайта конкурентов и предупредил что если не угомонятся то будет не 5 минут. Второй день полет нормальный.

    Остается вопрос:

    Вопрос: в чем разница между

    [sql]Select count(*) as count FROM adverts WHERE CURDATE()=FROM_UNIXTIME(date,"%Y-%m-%d"). [/sql]

    и

    PHP:
    1. <?php
    2. $stTime = mktime(0, 0, 0, date("m")  , date("d"), date("Y"));
    3. $endTime = mktime(23, 59, 59, date("m")  , date("d"), date("Y"));
    4. $f = mysql_query('Select count(*) as count FROM adverts WHERE `date` between '.$stTime.' and '.$endTime.'');
    5. ?>
    *не заметил ответ вверху*