- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF97:Пережить Slashdot-эффект
Материал из Linuxformat.
Содержание |
Как сделать Slashdot’о-упорным ваш сервер
- Ваш web-сервер подорвал силы, отбивая наплыв посетителей – аж по два обращения в секунду? Пол Хадсон покажет, как его излечить.
- Предупреждение: до старта
- Внесение изменений в настройки вашего сервера может привести к непресказуемым последствиям. Мы советуем использовать для этих тестов не занятый в основной деятельности сервер и перед внесением любых изменений в настройки делать резервную копию всех файлов системы. После изменения настроек Apache/MySQL не забудьте перезапустить сервисы, чтобы новые параметры вступили в силу
Digg, Reddit, Delicious, Furl, Newsvine и другие крупные сайты новостей посещаются миллионами пользователей, но, вообще говоря, лишь один из них популярен достаточно, чтобы дать имя явлению, вгоняющему в пот сисадминов: Slashdot-эффекту. Новости на нем, возможно, вам и не по вкусу, но Slashdot остается едва ли не главной отрадой хакеров в Интернете. Ссылка на ваш web-сайт, включенная в одну из новостей с главной страницы, приведет к вам за несколько часов более сорока тысяч человек, что чревато двумя исходами: либо огромным ростом прибыли от рекламы (больше народу прокликает ваши баннеры), либо тем, что ваш сервер расплавится, погрузив сайт в анабиоз ожидать волшебного поцелуя, который вернет его к жизни. Более того, если ваша история интересна широкой аудитории, то ее переопубликуют сотни других сайтов, источником новостей для которых является Slashdot, и посетителей может быть в несколько тысяч раз больше – если, конечно, ваш сайт не рухнет.
Но вот беда: большинство сайтов именно что рухнет. Slashdot-эффект получил свое название из-за того, что орды нагнанных им визитеров превышали пределы возможностей сайтов, и последние в конце концов падали. Если же вы настроены серьезно и хотите, чтобы ваш сайт был доступен всегда и везде, то есть много способов сдержать напор посетителей. Да, надо взяться за оружие и показать прыщавым слэшдоттерам, что вам плевать на 500 запросов в секунду, что вам приятно быть как Dugg и что Delicious остается только отирать с лица грязь, летящую из-под ваших копыт. Короче, пора превратить ваш медленный и средненький web-сервер в супербыстрый и супернадежный сервер вашей мечты.
Живи и дай умереть
[В заголовке – название известной песни Пола Маккартни, – прим. пер.]
Быстрота вашего кода особого значения не имеет: в конечном итоге все зависит от грамотности настройки Apache. Проблема в том, что люди думают: «Ну вот, сайт протестирован: он справляется, даже когда на него заходит сразу 20 человек – отлично!» 20 обращений в секунду – это неплохо, если вы размазываете число посещений в месяц равномерно по месяцу. Когда мы спросили, насколько опасен Slashdot, у эксперта LXF по web-технологиям Майка Сондерса, тот побледнел, задрожал и не сразу ответил: «Slashdot-эффект – это как тысяча термитов, грызущих ваши сетевые кабели». И когда он говорил о тысяче, он и имел в виду тысячу: двадцать обращений в секунду – это неплохо, но если ссылка на ваш сайт угодит на Slashdot, реально получить до тысячи обращений в секунду.
Первый эффект Slashdot возникает тогда, когда из-за огромного количества одновременно открытых соединений посетителям не удается соединиться с сервером, даже если он еще жив и нормально обрабатывает запросы. И они нажимают на кнопку «Обновить», и делают это снова и снова; и рано или поздно сервер в самом деле падает. Вот вам и второй эффект Slashdot: ваш сервер становится дымящейся развалиной.
Таким образом, решение проблемы состоит в выборе: обеспечить пользователям либо 100%-ную производительность ресурса при низ- кой загрузке и 5%-ную при высокой, либо 90%-ную при низкой и 70%-ную при высокой. Большинство людей предпочло бы второй вариант, потому что большую часть времени почувствовать разницу между 90% и 100%-ной производительностью невозможно. Но когда на сайт заходят тысячи посетителей и время имеет значение, различие между этими вариантами становится очевидным.
Эти два варианта разделены одной строкой в файле настроек Apache: KeepAlive. Она появилась в HTTP/1.1 и предназначена для того, чтобы разрешить постоянное соединение между клиентом и сервером. Браузер без поддержки KeepAlive соединяется с сервером, загружает страничку, отсоединяется, затем проверяет, есть ли на странице рисунки и другие вложения, после чего создает отдельные соединения для каждого из этих объектов. Это требует массы дополнительных действий, поэтому KeepAlive сохраняет одно соединение открытым около 15 секунд, позволяя пользователем загрузить в его ходе несколько файлов. Если на вашем сайте много графики, то включение поддержки KeepAlive способно уменьшить время ожидания (это не то же самое, что время загрузки страницы) примерно вдвое.
Ваш сервер Apache может поддерживать не более 256 одновременных соединений. Это много, но недостаточно для победы над Slashdot’ом, поэтому ваша цель – обработать эти запросы как можно быстрее, чтобы к серверу могли подсоединиться другие пользователи. Однако ваш сервер может быть не настроен на обработку такого количества одновременных соединений – загляните в файл настроек Apache сразу после настроек модуля mpm_prefork и проверьте значения параметров StartServers, MaxClients и MaxRequestsPerChild. Первый определяет количество серверов, создаваемых при запуске сервера, второй – количество серверов, для которых разрешен запуск, и третий – сколько запросов должен обрабатывать каждый сервер, прежде чем он будет снят. Если нагрузка вашего сайта высока, можно увеличить значение StartServers до 32, при этом убедившись, что значение MaxClients также высокое.
Однако здесь есть одно условие: сервер MySQL может обрабатывать ограниченное количество соединений. И если серверов Apache больше, чем соединений MySQL, то узкое место системы смещается к MySQL, и вам нужно увеличить количество соединений в настройках сервера MySQL.
Все это хорошо, но вспомним, что Apache поддерживает не более 256 одновременных соединений. Так что если пытаются подключиться 1000 пользователей, то Apache откроет соединения с двумястами пятьюдесятью шестью из них, обработает их запросы на все страницы и картинки, потом оставит соединение открытым на 15 секунд на случай, если клиенты затребуют еще что-либо, и, наконец, закроет их. Тут можно перейти к обслуживанию других пользователей. Здесь есть две основные проблемы. Во-первых, глупо сохранять соединение открытым в течение 15 секунд, когда его ждут сотни других пользователей. Во-вторых, приоритет загрузки изображений над загрузкой содержимого – штука неправильная по сути. Если отключить поддержку KeepAlive, то файл журнала запросов будет выглядеть примерно так:
User 1 запросил index.html
User 2 запросил index.html
User 3 запросил index.html
User 1 запросил foo.jpg
User 2 запросил foo.jpg
User 3 запросил foo.jpg
User 4 запросил index.html
User 1 запросил bar.jpg
User 2 запросил bar.jpg
User 3 запросил bar.jpg
User 4 запросил foo.jpg
User 4 запросил bar.jpg
Это куда справедливее, и вероятность того, что будет обслужены все пользователи, а не несколько приоритетных, намного выше. Убедились? Так и должно было быть! Чтобы отключить поддержку KeepAlive, откройте файл настроек Apache (обычно /etc/httpd/httpd.conf или /etc/apache2/apache2.conf) и измените строку
KeepAlive On
на строку
KeepAlive Off
После перезапуска Apache разницы в скорости вы почти не заметите. Но когда наступит критический момент и ваша история станет первой на Slashdot, тогда вы почувствуете разницу.
Оснастка PHP
Итак, Apache заработал на полной скорости; мы можем обратить наш взгляд на PHP, на котором написано большинство популярных web-сайтов. С PHP связаны две основные проблемы:
- 1 Это интерпретируемый язык, и скрипт должен компилироваться каждый раз, когда запрашивается страница. Как ни странно, время компиляции часто гораздо больше времени выполнения.
- 2 Код многих популярных проектов оставляет желать лучшего или слишком раздут. Примерами последнего могут служить PHPBB и PostNuke. Но даже если качество кода очень высокое (например, MediaWiki или Drupal), первая проблема все равно остается.
Есть и еще одна проблема, но от нее обычно страдают только системные администраторы Windows: если интерпретатор PHP запус- кается в режиме CGI, то он работает ужасно медленно. В Linux PHP чаще всего уже сконфигурирован для запуска как модуль Apache, так как этот способ обеспечивает наилучшее быстродействие. Если вы не уверены, создайте файл info.php в корневом каталоге web-сервера и добавьте в него следующие строки:
<?php phpinfo(); ?>
Загрузив этот файл в браузере, в разделе Server API вы должны увидеть строку Apache 2.0 Handler. Если ее нет, то PHP работает не с максимальной производительностью, и вам нужно установить пакет mod-php5 для сервера Apache.
Но даже если PHP настроен правильно, ваша работа только начинается: вам предстоит установить кэш и оптимизатор кода, разобраться, как сгенерировать отчет, если страницы загружаются слишком долго; наконец, все это должно работать как можно быстрее, потому что наша цель здесь – одолеть Slashdot, а не тратить кучу времени на редактирование файлов конфигурации.
Моментальное решение – Zend Platform, которая умеет все вышеперечисленное и даже больше. Эта среда хороша тем, что с ней можно ни о чем не думать – вы ее устанавливаете, и она автоматически кэширует и ускоряет выполнение всех страниц на сервере без вашего участия. Если сайт достаточно крупный, то вам, возможно, захочется увеличить количество оперативной памяти, выделяемой под кэш – по умолчанию это 64 МБ, вполне достаточно для кэширования тысячи PHP-скриптов приличного размера. Вспомним, что кэш кода позволяет компилировать скрипты PHP лишь один раз, сохраняя в оперативной памяти результат компиляции, что ускоряет их выполнение. В результате ваш сайт работает не хуже, чем раньше, а число обращений в секунду увеличивается в три-четыре раза.
Если вы хотите еще подхлестнуть свой сервер, попробуйте динамическое кэширование содержимого: страниц, не изменяемых обращением к ним. Например, допустим, форма с запросом GET вызывает только получение данных, а запрос POST преобразовывает страницу. Динамическое кэширование страниц в Zend Platform позволяет избежать ненужных обращений к базе данных для тех страниц, содержимое которых не меняется. На практике хранение кэшированных страниц в оперативной памяти обеспечивает дополнительное повышение скорости в 4 раза по сравнению с традиционными системами с кэшированием на жестком диске.
Если вы еще не убеждены, что Zend Platform может снять с вас тяжкое бремя, подумайте вот о чем: эта система бесплатна для разработчиков. Это означает, что пока эта платформа не работает на настоящем сервере, вы можете пользоваться ей совершенно безвозмездно. Стоимость лицензии на продукт – 685 фунтов в год без учета НДС, включая поддержку через Интернет.
Мой, мой MySQL
Многие используют для MySQL движок MyISAM – прежде всего потому, что он работает очень быстро, заставляя забыть о потенциальной возможности повреждения данных. Но если что-то уже с ходу работает быстро, это не значит, что нельзя добиться еще большей скорости. Этим мы сейчас и займемся, поскольку, кое-где подправив файлы конфигурации, можно реально увеличить скорость работы MySQL. Правда, с оговоркой: чтобы достичь максимальной производительности, потребуется много оперативной памяти.
PHP позволяет устанавливать постоянные соединения с сервером MySQL. На практике это означает, что каждый поток сервера Apache создает свое собственное соединение с базой данных. Преимущество такого подхода в отсутствии создания и закрытия соединений каждый раз, когда выполняется новый скрипт. Но это также означает, что сервер MySQL должен поддерживать как минимум столько одновременных соединений, сколько запущено серверов Apache. Второе неудобство – многие приложения PHP не поддерживают постоянных соединений; однако в вашем собственном коде с этим легко справиться.
Прежде всего откройте файл настроек MySQL – обычно это /etc/my.cnf, /etc/mysql/my.cnf или что-то в этом роде. В вашем дистрибутиве, скорее всего, уже есть файл с настройками по умолчанию, но могут быть и файлы с настройками для различных типов серверов. Запустите updatedb для обновления локальной базы данных, затем выполните команду:
locate my-
В Ubuntu эта команда находит файлы конфигурации MySQL в каталоге /usr/share/doc/mysql-server-5.0/examples, например, my-huge.cnf с конфигурацией MySQL для крупных серверов. Изучая эти файлы, можно узнать много нового, особенно потому, что в начале файла содержатся комментарии, поясняющие, для каких систем данный файл больше всего подойдет.
Если по-простому, учитывать надо следующие параметры:
- Размер ключевого буфера.
- Размер кэша запросов.
- Настройки совместного выполнения потоков.
- Размер кэша таблиц.
Это не полный список кэшей и буферов, используемых MySQL, но только изменение именно этих параметров приводит к заметным результатам.
Проверить, достаточен ли объем ключевого буфера, очень просто. Соединитесь с сервером MySQL и в командной строке выполните следующую команду:
SHOW STATUS LIKE ‘%key_read%’;
Вы получите два числа: Key_read_requests и Key_reads. Первое показывает, сколько раз в базе данных производилось считывание ключа индекса, а последний – сколько раз ключ не удавалось найти в кэше, и он считывался с диска. Для большинства сайтов необходимо, чтобы значение Key_read_requests было как можно больше по сравнению с Key_reads. Определить числовой показатель качества можно с помощью простой формулы:
100 – ((Key_reads / Key_read_requests) * 100)
Вы берете значение Key_reads и делите его на Key_read_requests, затем умножаете результат на 100 и вычитаете получившееся число из 100. Готово. Например, если у вас 30 Key_reads и 1177 Key_read_requests, нужно разделить 30 на 1177, получится 0.025, затем умножить это число на 100, и получится 2.55, наконец, вычесть это число из 100, и получится 97.45%. Это означает, что 97.45% всех ключей индекса считываются из кэша – это великолепно! Если у вас получилось менее 80%, то либо у вас проблемы, либо операций вставки, обновления и удаления данных просто очень много, что приводит к росту Key_reads. Если результат составил от 80 до 95 процентов, то нужно увеличить размер ключевого буфера – 256 МБ считается более или менее нормальным для больших баз данных. Если у вас получилось более 95%, беспокоиться не о чем.
Кэш запросов – это одна из cамых недооцененных характеристик MySQL. Он особенно удобен, когда объем данных большой, запросы выполняются часто, а данные изменяются редко. Когда вы выполняете запрос, объем результата которого не превышает 16 МБ, то этот результат помещается в кэш. Если тот же запрос поступает снова, его результат берется из кэша. Фокус состоит в том, что если данные в какой-либо из таблиц, участвующих в кэшированном запросе, изменяются, кэш автоматически очищается, чтобы результат снова формировался непосредственно из базы данных.
В файле настроек MySQL размер кэша запросов определяется переменной query_cache_size в разделе [mysqld]. Например, рекомендованный минимум составляет
query_cache_size=16M
“M” в MySQL означает МБ; таким образом, эта строка устанавливает размер кэша в 16 МБ. Но если размер оперативной памяти позволяет – а он должен – установите это значение в 64M, чтобы кэшировалось больше запросов.
Последние два параметра лучше сделать побольше. Для кэша таблиц обычно вполне достаточно 128; если у вас больше 128 таблиц, просто увеличьте это число. Что касается одновременного выполнения потоков, то число параллельных потоков должно быть вдвое больше числа ядер в вашем процессоре – стало быть, для четырехъядерного процессора установите его в 8. Вот и все: перезапустите сервер MySQL для принятия новых настроек и наслаждайтесь обретенной скоростью!
Улучшенный мониторинг MySQL
MySQL входит в большинство дистрибутивов, поэтому многие не знают, что существует превосходная коммерческая версия продукта – MySQL Enterprise. Эта версия использует тот же сервер, что и MySQL, но с выходящими каждые три месяца пакетами обновления, службой поддержки, и – главное – сетевым монитором MySQL. Это очень толковый набор программ, который локально запускает собственный web-сервер и сервер MySQL, подключаемые ко всем остальным серверам MySQL и формирующие подробный отчет об их работе. Если один из серверов перестает отвечать на запросы, или загрузка его процессора или использование оперативной памяти достигает предельного значения, сетевой монитор отправляет сообщение об этой проблеме на web-интерфейс администратора и даже выводит небольшие графики использования ключевых буферов, числа соединений и т.д.
Кроме того, предоставлятся консультативный сервис MySQL, который сканирует MySQL-сервер и формирует список возможных проблем: нет ли правил, которыми вы пренебрегаете? Возможны ли проблемы с безопасностью в вашей конфигурации? Самым полезным из таких сервисов являются советы по использованию памяти: ведется наблюдение за использованием буферов и даются рекомендации по оптимизации настроек – вся умственная работа выносится за скобки…
Прежде чем вносить изменения в конфигурацию Apache или MySQL, снимите характеристики вашего сайта. Лучший способ это сделать – это запустить на другом компьютере утилиту ab: она несколько тысяч раз обращается к серверу и оценивает время отклика. Для начала запустите эту команду
ab -n 10000 -c 100 -k http://localhost/index.php
Она отправит на ваш сервер 10000 запросов, разделенных на сто одновременных соединений. Ключ -k означает «использовать поддержку KeepAlive», что позволит вам оценить характеристики сервера с поддержкой KeepAlive и без нее.
Настройки для отдельных приложений
Вместе с MySQL Enterprise вам предоставляется доступ к службе поддержки при возникновении каких-либо проблем, однако пока вы не особо налегаете на MySQL (особенно с репликацией), проблемы вряд ли возникнут. В любом случае, следует попробовать 30-дневную тестовую версию MySQL Enterprise – установить ее на свой сервер, дать ей поработать несколько дней на настоящем сайте и посмотреть, не посоветует ли эта система что-нибудь полезное.
Некоторые сложные приложения на PHP содержат встроенные средства оптимизации, помогающие ускорить их выполнение, но если вы пользуетесь Zend Performance, то постарайтесь не вмешиватьсяв его работу. Например, MediaWiki (приложение, на базе которого работает Wikipedia) имеет возможность кэширования страниц (опция memcache). «Скомпилированные» страницы хранятся в оперативной памяти и при необходимости извлекаются оттуда. Это может реально увеличить производительность, так как MediaWiki – крупное приложение, очень требовательное к системным ресурсам при преобразовании кода из нотации wiki в HTML.
Но дело в том, что Zend Platform способно обеспечить гораздо лучшее кэширование, чем MediaWiki, и, объединив кэши, можно использовать оперативную память наилучшим образом. Помните, что memcache – это общий способ кэширования, тогда как Zend Platform предлагает решение, направленное на PHP: она кэширует скомпилированные скрипты и выводимые страницы и автоматически отслеживает изменения на сайте, поэтому всегда понятно, когда нужно обновить кэш. В MediaWiki вы в лучшем случае получаете кэш вывода, который не идет ни в какое сравнение.
Другие популярные проекты содержат различные средства оптимизации, которые нужно изучить более внимательно. Например, Drupal содержит средства оптимизации кэширования и сжатия данных, но мы опять же рекомендовали бы вам оставить кэширование отключенным (как по умолчанию), зато попробовать включить сжатие CSS. До и после внесения изменений всегда снимайте контрольные характеристики, чтобы убедиться в том, что вы случайно не замедлили работу системы.
Итак, наше краткое руководство по оптимизации web-сервера подошло к концу. Применив эти настройки, вы сможете пережить испытание не только Slashdot’ом, но и Slashdot’ом в сочетании с Digg, StumbleUpon, Furl, Reddit, Delicious и другими крупными сайтами – на деле вас ограничивает лишь объем оперативной памяти и частота процессора. Вам осталось только придумать что-нибудь этакое, чтобы ваш сайт засветился на Slashdot, а вот с этим, боюсь, я помочь уже не смогу… LXF