Как разместить на сервере 10000 клиентов или даже больше
Сегодня я хочу сделать новогодний подарок, а так как самое ценно в мире - это опыт, знания и технологии, то хочу поделиться этим всем с вами.
🕛 02.01.2010, 01:18
Надеюсь, что мой трехлетний опыт работы системным инженером/архитектором поможет некоторым хостерам открыть для себя новые горизонты.Следует отметить, что под клиентом воспринимается обычный аккаунт на LAMP (Linux+Apache+Mysql+PHP), с одним-двумя виртхостами и работающим со всеми опциями php.ini по умолчанию. Основное - это 16MB RAM и 30 сек исполнения. Вполне достаточно для большинства движков - Wordpress, Drupal и Joomla.
Железо
Конечно, самое главное - это грамотно подобрать сервер. Опытным путем была найдена оптимальная связка - Dell 905 + корзина MD 1000. Немного подробнее о конфигурации. Разумеется, что сервер будет работать с двумя 6-и ядерными Оптеронами. Памяти для ~15k клиентнов, а именно столько работало у меня на сервере, хватало 128G, но можно пробовать и 64G+своп, если конечно вам не жалко своих клинетов ;)
Про корзину говорить особо нечего - каждому нужно место под сайт. Единственное что - надо грамотно разбить сторадж, но об этом позже. Можно использовать SAS, а можно - более дешевые SATA. В моем случае для 15k хватало SATA, но если вы планируете больше - то придется брать SAS.
Софт
Разумеется, на сервере должен работать только веб. MySQL - только на отдельном сервере. Почта - тоже, причем отправка идет чем-то легким, типа ssmtp, а не монстрами типа exim/sendmail. Но вобщем-то это не главное. Есть более важные вещи, которые надо учитывать.
Прежде всего, это соотношение использования оперативки и разрядности. Уверен, что все знают, почему 64-х битные бинарники занимают больше оперативки при работе. А вот кто знает, какое самое узкое место при работе множества сайтов? Правильный ответ - это их логи.Именно логи отнимают большую часть ресурсов сервера, так как работа с диском на запись - самая медленная часть системы. Вывод просто - надо что-то делать с логами и использовать 32-х битный софт вместо 64-х битного.
С логами сначала была идея сделать mod_log_spread под второй апач. Или даже использовать первый только для логов. Но тут помог статический опрос - большинство клиентов не пользовалось логами веб-сервера и их по умолчанию просто отключили. Тем, кто просил - включали по запросу. И для записи логов естественно использовался отдельный диск.
Самое вкусное
Но как быть с 32-х битным софтом? И с тем, что при более 1000 виртхостов апач ведет себя все хуже и хуже? И тут нам поможет OpenVZ! Да-да, именно так - разбиваем сервер на 32-х битные виртуалки, пускаем в каждом свой апач - и вуаля, все это отлично работает, так как одинаковые виртуалки неплохо шаряться памятью между собой, благодаря OpenVZ. А учитывая, что можно подключить отдельный диск как произвольную директорию для каждой виртуалки - то проблема с логами уже решена только благодаря этому!
Ну а теперь немного о том, как же это все работало с технической точки зрения. Сразу скажу - апач я пересобирал, выкинув много ненужного, в том числе ssl, и выбрав MPM Worker - тредовый апач. Естественно, что каждая виртуалка использовала все 12 ядер, и число процессов для апача тоже было 12. Как и воркеров для Nginx.
Кстати о Nginx - я говорил о том, что там нужно отдавать всю статику напрямую, не трогая апач? Наверное нет, так как это само собой разумеется. А вот о том, как работал PHP - стоит поговорить более детально.
Разумеется, в MPMWorker mod_php нельзя запускать на продакшене - что бы там не говорили доморощенные «одмины», он падает и будет падать ибо многие его расширения не умеют работать в тредах, о чем собственно уже много говорилось. Таким образом остался единственный вариант - mod_fastcgi + PHP-FPM. И естественно, что в каждой виртуалки крутилось по 12 процессов PHP.
Таким образом, каждая виртуалка представляла из собой связку из 32-битных приложений: nginx+apache-worker+php-fpm. Для каждой виртуалки в корзине создавался Raid-1, для логов был сделан отдельный общий диск, который подключался в директорию логов. Потом я посмотрел на это все и подумал - а если у нас общий диск под логи, почему бы не сделать один общий nginx на все виртуалки? Ведь OpenVZ работает с виртуалками на уровне файловой системы, а не блочными устройствами, и соответственно все файлы доступны из хардварной ноды, только нужно подставить путь к директории виртуалки.
Сказано - сделано. Продакшн сервер на 10k виртуалок должен состоять из:
* 32-х битных виртуалок с 1k хостов на каждой * Выделенного диска под каждую виртуалку * Апачем в тредовом режиме + PHP-FPM, с учетом процессов по числу ядер * Единого nginx на все виртуалки для отдачи статики и акселерации * Выделенного диска под запись логов + их минимизация
Ну и в завершение - бонус про файловер. Если набить стойку таким железом + дать на 1 сервер больше, чем корзин, то выходит очень отказоустойчивая система. Все данные лежат в корзине, а на сервере - обычный скрипт, который запускает каждый найденный диск как контейнер OpenVZ + подключает выделенный диск в каждую виртуалку для логов. Если один из серверов выходит из строя, то мы просто подключаем резервный к корзине, а сломанный спокойно отдаем в ремонт.
P.S. Стоимость железа на размещение ~500k клиентов с учетом скидок (покупалось через Дата-Центр в США) составила ~90k$. Или иначе говоря - себестоимость полста клиентов - всего девять баксов без учета оплаты стойки, питания и трафика.