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

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

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

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

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

Естественно, времени мне хватило только чтобы это увидеть, запустив команду top. Уже через минуту сервер перестал отвечать на запросы, и пришлось его вновь перезагрузить, и сразу после перезагрузки выключить apache. Теперь я гарантированно получил сервер, который не израсходует все ресурсы. Начал проводить анализ, я вывел число открытых соединений командой netstat и ужаснулся. Было более 10000 установленных соединений с 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;


Как только я это сделал, нагрузка на сервер резко упала. Однако мы получили множество неудобств, связанных с администрированием и комментированием. Несмотря на неудобство, проблема была решена. Однако сознание подсказывало, что включать вручную такое кэширование не всегда будет время и возможность, а оставлять как есть не вариант для автора блога. Таким образом, пришлось запрещать кэширование для авторизованных пользователей, и пользователей, оставивших свои комментарии. В итоге получается примерно такая секция 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;
}
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 на сайте клиента, после того, как сервер окончательно поднялся, показывал 6000 посетителей онлайн. Эта цифра быстро падала, потому что актуальность запроса, по которому сайт был в топе всех поисковых систем, терялась каждую минуту. К концу дня, количество посетителей стало семизначным, но владелец ресурса до сих пор смотрит на меня волком, потому что цифра могла быть в разы выше, как и его доход.

Используя этот конфиг могу с уверенностью сказать, что сервер переносит несколько подобных сайтов. Так как мой проект после добавления в Google-Новости стал привлекать много трафика, как собственно и с Яндекс-блогов.
Support the author
Share post

Similar posts

Comments 38

    0
    Но ведь если сделать эти не очень хитрые действия, можно было бы избежать волчьего взгляда автора блога?

    И спасибо за интересный случай (проверю свой сервер).
      +11
      Для этого владелец блога должен был почесать репу заранее.
      Вобщем, очередное подтверждение того, что скупой платит дважды.
        0
        Действительно, это так.
        К сожалению, эти действия были сделаны слишком поздно.
        +15
        Читаю подобные success stories, и всегда не понимаю, ну зачем в этой всей связке apache? Есть же php-fpm, в который прекрасно проксируется всё из nginx и без дополнительной прослойки. Я не говорю что это бы решило проблему, я просто не понимаю — зачем он там?
          0
          Объясню: Потому что «из коробки» уставнолен apache. Хорошо еще теперь стали nginx ставить. А как говорится: «Работает? Не трогай.». Именно в критических ситуациях и начинаем все менять. таких как эта. На данный момент, заметной нагрузки нет, и тотальная миграция на php-fpm в очередной раз откладывается. Хотя нутром понимаю, что зря.
            +3
            У меня была похожая ситуация. Сильно удивило, что сначала проблемой стал Апач, а только потом MySQL. Возможно, можно было и Апач настроить, но php-fpm сразу решил проблему «из коробки»
            +2
            Частая аргументация — из-за рерайтов\htaccess
              0
              Под WP для рерайтов я юзаю такой костыль:

              if (!-e $request_filename) {
              rewrite (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ /index.php last;
              }

              Либо пихаем его в location /, либо подсасываем из файла инклудом. Вкупе с плагином nginx Compatibility для самого WP работает на ура. Всё же остальное, что мы юзаем (phpBB, IPB, свои самопальные вещи) работают на ура безо всякой адаптации.
                +3
                Как бы If is Evil
                : )
                  –2
                  Не в такой простейшей конструкции :)
                  +4
                  Жуткий костыль. Читайте про try files.

                  + Зачем велосипед изобретать? Всё описано подробно в мануалах wiki.nginx.org/WordPress и codex.wordpress.org/Nginx
                    0
                    Это было первое, что мне пришло в голову, когда я решил перекинуть генерацию статики на FPM, и когда я увидел, что из коробки не заработало. Спасибо за ссылки, почитаю, переработаю.
              +10
              Совершенно плевая нагрузка, если честно. Кроме того 6000 онлайн это не 6000 конкурентных или запросов в секунду.

              Рекомендую открыть для себя: MaxClients, php-fpm (pm.max_children) и не ронять сервер сервер из-за одного сайта. Так же рекомендую: "56. Подводные камни при использовании кэширования в nginx"
                0
                Спасибо. С удовольствием изучу материалы.
                  0
                  Просто у меня ситуацию похожая. На VPS-ке, не дедике даже еще, кроме своего сайта держал блог друга. Но у меня изначально все на nginx+php-fpm и я его выделил одни рабочий процесс для блога (pm = static, pm.max_children = 1). Потреблял он в простое где-то 20МБ ОЗУ. И тоже к нему раз посетители нагрянули. Что-то под 1500 по статистике гугла. Так это ни то, что сервер уронило, у него на даже на блоге не было ни одной 50х ошибки.

                  Так что переходите на связку nginx+php-fpm и поймите, что 6000 онайнеров по статистике гугла это мелочи. Вот 1000 в секунду это уже более ощутимо, по крайне мере для WP (ибо я вот на своем PHP движке могу обработать такое количество уложивший в ~300МБ ОЗУ). Кстати лучше ставить стразу 5.4. Как писал вот тут автор у него эта версия показала очень хорошие результаты: "PHP-FPM на рабочем сервере под Debian 6".
                0
                Интересный материал у Котерова. Добавил в букмарки. Действительно разжеванный конфиг порой сложно найти.
                0
                На самом деле можно было переписать правила для WP Super cache из .htaccess в конфиг nginx и оставить все как есть, потому что в результате вы просто перебросили кеширование в nginx, потеряв при этом нужный контроль в WP. И вместо долговременного кэширования с правильным сбросом и по времени и по изменениям вам пришлось делать корткоживущий кэш.
                  0
                  Действительно. Еще один способ, как вариант. Спасибо.
                • UFO just landed and posted this here
                    +1
                    Такое ощущение что раз в месяц подобные топики постят habrahabr.ru/post/110958/
                      +1
                      статья ни о чем. хотябы назначение директив и методики выбора значений бы расписали. А то больше походит на историю «как я включил кеш на nginx, быстро погуглив»
                        +1
                        Спасибо за замечание. Учту.
                          0
                          кроме того вы в глобальном контейнере обьявляете некоторые директивы, а в последующем снова их обьявляете в низлежащих. Непонятно, зачем?

                          proxy_pass 127.0.0.1:8080;
                          proxy_cache_valid 200 3m;
                            0
                            Не понял почему так, действительно некоторые секции можно было убрать. Исправил.
                          0
                          Автор говорит на это 2 часа ушло.
                          0
                          Очень хорошие результаты дает кеширование через memcached.
                            0
                            а что кешировать? wordpress умеет юзать memcached?
                              0
                              В комментарии ссылка на плагин, который этому учит.
                                0
                                ухты, спасибо, хоть чтото полезное для себя открыл.
                            0
                            Конфиг взят отсюда?
                              –1
                              Увидел «CGI»… дальше даже не интересно.
                                –1
                                varnish наше все. тоже были проблемы с нагрузкой, после настройки кеширования сайт летает.
                                  0
                                  1. Mysql cache первым делом должен был быть включен, как так возможно запускать сервер без его включения?

                                  2. «Я обнаружил, что был активирован плагин для кэширования WP Super Cache, который я выключил, потому что при выполнении самую большую нагрузку на файловую систему давал именно он.»
                                  Файлы отлично кэшируются в *nix, и тем более если это одна страница, то она всегда находится в кэше файловой системы в памяти и отдаётся мгновенно (а по тестам двухгодовалой давности ещё и быстрее даже чем отдаёт APC). Как может случиться описанная здесь ситуация?

                                  3. Не увидел слова «APC», он включен?

                                    0
                                    1. Исторически сложилось.

                                    2. Не вникал в настройки плагина, не до того было. Возможно был неправильно настроен, но нагрузку давал заметную.

                                    3. Включен.
                                    0
                                    WP Super Cache отличная вещь, если настроить nginx брать файлы прямо из его папки.
                                    У меня на блоге бывали ситуации, когда php-fpm просто умирал, а nginx продолжал отдавать статику как ни в чем не бывало.
                                    tigors.net/configure-nginx-for-wordpress/

                                    А если скомпилировать nginx с параметром
                                    --with-http_gzip_static_module

                                    И включить в WP Super Cache Сжимать страницы для єкономии трафика, то можно еще и канал экономить.
                                      0
                                      Мне стоит, наверное, пристальнее поглядеть в сторону этого плагина. Спасибо.

                                    Only users with full accounts can post comments. Log in, please.