Миллион посетителей против сервера

Так как это моя первая статья в рамках этого сайта, мне хотелось бы представиться и познакомить вас с моим сервером, о котором пойдет речь ниже. Я программист из Алтайского края города Бийска, где мои услуги абсолютно никому не интересны или интересны, но за прожиточный минимум. Именно это стало причиной моего ухода в онлайн, где абсолютно нет географии, благодаря чему есть работы для специалиста из глубинки.

Мой сервер, который и будет героем последующего повествования — это обычный арендованный у FirstDedic сервер среднего класса с процессором DualCore Xeon E3110 3.00Ghz. Оперативной памяти было установлено 4 Гб, жесткий диск 500 Гб. На сервере использовался nginx 1.01 в качестве frontend, и apache 2 в качестве backend, с запуском скриптов в режиме CGI.

История приключилась с сайтом, который был размещен на моем сервере, собственно, не сайт, а чужой личный блог. Ранее на блоге наблюдались пики трафика до 10к в сутки, но с подобной нагрузкой сервер справлялся на ура.

И вот, в один прекрасный «Женский день», утром, приходит SMS от сервиса мониторинга сайтов, что сервер недоступен. Естественно, от такой новости мгновенно просыпаюсь, и пробую пинговать сервер. Пинг присутствовал, но очень вялый. Соединение по SSH установить невозможно, потому что все ресурсы сервера отданы неизвестному процессу, или процессам.

Соединившись по KVM, я отправил сервер в перезагрузку, и сразу после загрузки соединился по SSH. В процессах, я увидел страшную картину: запущено около 1000 процессов php от имени автора блога, кроме того, Load averages больше сотни. Очень страшный показатель, который показывает, сколько приходится ожидать процессу своей очереди на порцию ресурсов.

Естественно, времени мне хватило только чтобы это увидеть, запустив команду top. Уже через минуту сервер перестал отвечать на запросы, и пришлось его вновь перезагрузить, и сразу после перезагрузки выключить apache. Теперь я гарантированно получил сервер, который не израсходует все ресурсы. Начал проводить анализ, я вывел число открытых соединений командой netstat и ужаснулся. Было более 10к установленных соединений с nginx. Это значит, что за последнюю минуту было 10 тысяч попыток зайти на сайт клиента – хорошая нагрузка.

Попытавшись порыться в настройках WordPress, естественно с согласия клиента, Я обнаружил, что был активирован плагин для кэширования WP Super Cache, который я выключил, потому что при выполнении большую нагрузку на файловую систему давал именно он. Выключив плагин, сайт стал выполнять очень много запросов в базу данных – неудивительно. Поэтому первым делом я включил систему кэширования запросов в MySQL, так как нагрузку давала всего одна страница, на которую и было множество переходов. После включения кэширования запросов, база данных вздохнула свободнее, но не настолько, насколько хотелось бы, притом, что основную нагрузку теперь давал сам Wordpress.

Выключив все возможные плагины и переписав тему с наименьшим количеством запросов, нагрузка не уменьшалась. Пришлось идти на крайние меры — я включил принудительное кэширование проксированных запросов в nginx. Для этого я прописал в секции http следующую строку

proxy_cache_path /path/to/cache levels=1:2 keys_zone=wpblog:10m max_size=10m;


В нужную нам секцию server прописываем:

proxy_cache_valid 200 3m;
proxy_cache wpblog;
proxy_pass http://127.0.0.1:8080;
proxy_cache_valid 200 3m;


Как только я это сделал, нагрузка на сервер резко упала. Однако мы получили множество неудобств, связанных с администрированием и комментированием. Несмотря на неудобство, проблема была решена. Однако сознание подсказывало, что включать вручную такое кэширование не всегда будет время и возможность, а оставлять как есть не вариант для автора блога. Таким образом, пришлось запрещать кэширование для авторизованных пользователей, и пользователей, оставивших свои комментарии. В итоге получается примерно такая секция server

proxy_cache_valid 200 3m;
location / {
if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
		set $do_not_cache 1;
	}
	proxy_no_cache $do_not_cache;
	proxy_cache_bypass $do_not_cache;
	proxy_cache wpblog;
	proxy_pass http://127.0.0.1:8080;
	proxy_cache_valid 200 3m;
}
location ~* wp\-.*\.php|wp\-admin {
	proxy_pass http://127.0.0.1:8080;
}
location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
root /path/to/static;
	access_log off;
	expires max;
	add_header Last-Modified: $date_gmt;
}
location ~* \/[^\/]+\/(feed|\.xml)\/? {
	proxy_pass http://127.0.0.1:8080;
}


После этого неудобства в работе полностью компенсируются бесперебойностью.

Как итог ко всему вышеописанному, сервер был недоступен в течение 2 часов, за это время поток трафика значительно уменьшился, но после этого случая были и другие, которые сайт успешно выдержал, не дав ощутимой нагрузки на сервер. С тех самых пор стараюсь на все размещенные сайты на WordPress ставить такую конфигурацию.

Google Analytics на сайте клиента, после того, как сервер окончательно поднялся, показывал 6к онлайн. Эта цифра быстро падала, потому что актуальность запроса, по которому сайт был в топе всех поисковых систем, терялась каждую минуту. К концу дня, количество посетителей стало семизначным, но владелец ресурса до сих пор смотрит на меня волком, потому что цифра посетителей могла быть в разы выше, как и его доход.


6 комментариев

avatar
Может быть автор сайта после прочтения статьи догадается, сколько вы ему помогли заработать? Если бы не ваш титанический двухчасовой труд, я думаю, что автор только к вечеру бы смог увидеть свой сайт живым…
avatar
Мне вот интересно, что бы происходило с этим сайтом на любом более-менее-известном shared хостинге? У кого был подобный опыт?
avatar
На шареде его бы просто выключили и отправили на мыло владельцу просьбу о переезде на выделенный сервер.
avatar
Примерно так и думал
avatar
Сначала бы лег весь хостинг, а потом уже вручную отключили бы именно это сайт :)
avatar
Действительно, за такой подход нужно огромное спасибо говорить, а не волком смотреть.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.