Pull to refresh

История развития и оптимизаций одного высоконагруженного ресурса

Reading time5 min
Views14K


Введение

Все началось с того, что я стал системным администратором у одного провинциального Интернет-провайдера. Помимо администрирования различного рода ресурсов, мне в присмотр достался один молодой, но бурно развивающийся ресурс. Ресурс представлял из себя классический LAMP проект. Сайт, на котором генераторами контента являлись обычные пользователи.
* К слову, в то время я ничего не понимал в *nix системах, хоть и все сервера которые мне достались, были именно на нем, разбирался я во всем этом достаточно быстро.

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


nginx + php-fpm

На помощь пришел Google. Как выяснилось, что для проектов с высокой нагрузкой люди используют php в режиме fast-cgi. Оказалось, существует несколько схем реализации такого режима, но в итоге предпочтение было отдано русским разработкам, связке nginx (Игоря Сысоева) и php-fpm (Андрея Нигматулина). Выигрыш в производительности, по сравнению с Apache и его mod_php достигается за счет того, что php-fpm создает n php процессов, которые в последствии висят в системе и обрабатывают скрипты переданные от веб-сервера. При такой схеме экономится время и ресурсы системы на вызов php интерпретатора. Не спрашивайте, почему я не выбрал какой-нибудь spawn-fcgi c lighttpd, я не хочу начинать холиваров на эту тему, да и принципиального значения это не имеет. Производительность системы возросла, нагрузка спала, я на некоторое время вздохнул с облегчением.

eAccelerator

Следующим шагом на пути к высокой производительности установка php-акселератора. Суть его работы заключается в кешировании бинарного кода скрипта. Действительно, зачем тратить драгоценное процессорное время на перевод скрипта в бинарный код при каждом обращении? Таких обращений к одному и тому же скрипту могло быть до 100 в секунду, поэтому eAccelerator пришелся как нельзя кстати. После его установки производительность системы снова возросла, нагрузка прилично спала, время генерации страниц резко уменьшилось, а пользователи снова стали довольствоваться ускоренным ресурсом.

MySQL index'ы

Должен заметить, что до работы в компании я прилично баловался с php, поэтому я прекрасно разбирался в коде ресурса и понимал что и зачем там нужно, однако я понимал что как и в любом коде, там есть узкие места и я решил начать их поиск. После добавления в проект таймеров, отсчитывающих время выполнения php и время выполнения sql-запросов, узкое место нашлось сразу же. Ресурс был основан на одной open-source CMS и судя по коду, некоторые из разработчиков не имели представления о индексах в MySQL. Чтож, начались долгие выявления и переделки проблемных запросов, а так же добавления индексов туда, где они действительно нужны. EXPLAIN стал моим спутником на ближайшие несколько дней. В итоге, время выполнения sql-запросов местами сократилось до 10-20 раз и опять начались счастливые дни для дорогих пользователей.

Memcached

К тому времени как нагрузка снова оказалась в полке, начальство уже выделило под ресурс полноценный сервер. Но у меня уже играл спортивный интерес. Когда время генерации страницы падает с 2-х секунд до 0,5 секунд это очень и очень вдохновляет, но мне хотелось большего. Мне хотелось избавиться от тяжелых sql-запросов совсем, оставить лишь критичный минимум. Бороздя просторы я наткнулся на доклад Андрея Смирнова: «Web, кэширование и memcached» (выступление на HighLoad++ 2008). Действительно, это то, что нужно! Memcached – простейший и в то же время высокопроизводительный кеширующий сервер, разработанный в свое время для livejournal.com, как нельзя кстати вписался в мою схему. К сожалению, использовать memcache на полную не представлялось для меня возможным, ведь моя работа не ограничивалась этим веб-ресурсом, однако было сделано все равно многое. Я использовал memcached для кеширования результатом sql запросов, либо хранения уже готовых отрендереных блоков. На многих страницах сайта время их генерации сократилось до ужасно маленьких цифр — 0,009с! Это было самым большим открытием и достижением за все время.

Sysctl и unix-sockets

Еще один не маловажный момент в борьбе за качество ресурса это тюнинг sysctl. На больших нагрузках дефолтная конфигурация оставляет желать лучшего. Пару недель было потрачено на нахождение оптимальных параметров сетевой подсистемы. Так же по возможности php-fpm, memcached и MySQL были повешены на unix-socket’ы. В итоге, в пиковые нагрузки сервер отдает контент так же быстро, как и без нагрузок.

Sphinx

К тому времени как я осилил кеширование, мне стало интересно, а возможно ли что-нибудь еще ускорить? Естественно! Поиск был самым слабым местом сайта. Догадываетесь почему? Верно! Там использовалось страшное зло – LIKE в sql запросе. Тут и пришел на помощь поисковой движок Sphinx! К сожалению, в моем случае получилось использовать Sphinx лишь для саггестов (всплывающих подсказках во время поиска), т.к. обновление основной sql таблицы было очень частым, а актуальность данных была очень важна, поэтому пришлось отказаться от него. Однако будь у меня больше времени на детальный разбор этого момента, возможно, я справился бы и с этой проблемой и Sphinx стал бы еще одним ключевым моментом в развитии сервиса.

MySQL в tmpfs

С момента всех моих тюнингов и оптимизаций прошло очень много времени. Ресурс стал значим для компании, на его поддержку выделяли деньги и вот уже его обслуживали 2 сервера. Первый выступал в роли веб сервера и обрабатывал php, второй использовался под MySQL. Но развитие не стояло на месте и вот ресурс доходит до 600 обращений в секунду, обе части ресурса перестают справляться. Затыки как на уровне php, так и на уровне MySQL. После получения третьего сервера, встал вопрос о его масштабировании, однако идеального варианта придумать я не мог. И вот на страницах хабра увидел тему о MySQL в tmpfs. И подумал, а почему бы и нет. Провел некоторые подготовительные работы с базой. Максимально сократил БД путем удалений маловажных но «прожорливых» функций. Убрал некоторые функции логирования в БД. В конечном счете, вес БД сократился с 11 до 2,5ГБ. И вот, было решено использовать 2 сервера под php, а на 3-м запустить MySQL с «допингом». С бэкапом очень хорошо справляется стандартная утилита mysqlhotcopy (1,5 секунды и готово!). Так и поступил. Нагрузка на MySQL снизилась в 4 раза, производительность тоже возросла.

Заключение

К чему я это все решил рассказать? Возможно, эта статья окажется интересной определенному кругу лиц, столкнувшемуся с подобными проблемами. Найди я в свое время что-то подобное, мне это очень бы помогло. Еще ресурс претерпит большие изменения. Все будет переписано, и от старого ничего не останется кроме контента и юзеров. Для меня видится закат всех моих наработок, однако я получил огромный опыт благодаря им, а опыт – бесценен. А статья, станет для меня памятью о том, что я когда-то делал.

В процессе работы, мне очень помог мой коллега (CentAlt), который всячески поддерживал меня во всех начинаниях и за это ему огромная благодарность. Кстати, возможно некоторые из вас его знают. Он держит один очень полезный репозитарий для Centos, в котором можно найти свежие версии nginx, php-fpm, unbound, clamav, postfix, dovecot и т.д.

Статья не претендует на первенство или популярность. Это не инструкция о том, как нужно или не нужно делать. Это история одного высоконагруженного проекта, который мне довелось развивать и админить.

Спасибо за то, что дочитали до конца!
Tags:
Hubs:
Total votes 208: ↑198 and ↓10+188
Comments56

Articles