Как выдержать миллионы запросов

Как выдержать 100 пользователей одновременно

Простой расчет показывает, что для контентного проекта, частота обновления где-то 5-20 сек на стр, т.е нагрузка от 100 пользователей должна быть около 20 rps. Для игрового проекта нагрузка повышается до 200 - 400 rps. Это не большие нагрузки. Как правило, проект такого уровня сидит на общем (шаред) хостинге и если шаред-сосед начнет «подсаживать» сервер «тупыми» запросами, то ни какая оптимизация тут уже не поможет. Повезло, если проект размещается на отдельном сервере. Но, большинство проектов реализовано на популярных портальных системах или ЦМС, таких как Drupal, Wordpress, Symphony, 1C-Битрикс,OsCommerce и пр. Оптимизировать в них, что-либо дело сложное и не благодарное. Данные системы универсальны, и по этому изначально не оптимальны. Но они со своими задачами прекрасно справляются и по этому они весьма популярны.

Про серверную оптимизацию средних интернет-проектов написано предостаточно статей. Как правило, все рекомендации сводятся в основном к трем пунктам:

  1. Использование акселератора
  2. Оптимизация запросов
  3. Кеширование HTML страниц или результатов запроса.

Как выдержать тысячи пользователей одновременно

Для расчета нагрузки от 1000 пользователей одновременно нагрузка повышается в среднем 2500 - 5000 rps. Как правило, один, даже выделенный сервер такие нагрузки не сможет выдержить. В этом случае организуется кластер, который включает: два или более WEB серверов, один-два серверов БД, балансировщик нагрузки и сервер бэкапа. Иногда балансировщик нагрузки совмещают с бэкап-сервером. Если размер базы не очень огромный то и данные могут быть физически умещены на одном сервере. Для распределения нагрузки организуется репликация и данные отдаются одновременно с нескольких серверов баз данных.

Репликация, от анг. Replication – это механизм синхронизации содержимого нескольких копий объета, в нашем случаи таблиц данных. При репликации, изменения сделанные на одном копии объекта (в одной таблицы данных), распространяются на другие копии. Репликации бывают: master-slave и master-master.

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

Master сервер – это сервер, изменения на котором распространяются на все slave-сервера. Если используется схема master-master, то изменения, произведённные на любом из серверов, переносятся на все остальные сервера.

Ниже на рисунке приведена типовая схема такого вот кластера.
3_0.jpg
4_0.jpg

В подобной схеме важно решить, как будет организовано взаимодействие между WEB сервером и серверами БД. Взаимодействие может быть осуществлено как напрямую, так и через посредников (рис 2).

В качестве таких посредника используются специализированные прокси сервера: pl_proxy(pgsql) или mysql-proxy в зависимости от используемой БД в проекте базы данных. Со стороны WEB сервера происходит прозрачный доступ к источнику данных.

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

Если используется схема подключения «напрямую» к серверу БД, то управление логикой соединения ложится на само Приложение. Недостаток такого подхода в том, что при использовании master-slave репликации, возможно придётся держать два соединения с БД, одно на чтение – выполнение операций SELECT, и второе на запись: выполнение операций INSERT,UPDATE,DELETE.

Если для mysql – открытие соединения, операция отностительно дешовая, то для postgresql - операция открытия соединения связана с рождением нового процесса, что является относительно ресурсоемко для нагруженного проекта.

Каждый проект имеет много особенностей, и его конечная архитектура реализуется в зависимости от них. Если в проекте представлено много статического контента (фото, музыки, видео), то его отдачу целесообразно организовать отдельно настроенным WEB-сервером, оптимизированным под отдачу статики (в данном примере не рассматривается онлайн видео вещание). Многие проекты используют, в зависимости от особеностей, разные NoSQL решения. Наиболее популярные: Redis, MongoDb, CouchDb.

Например, Redis часто используют, как хранилище сессий или сервер очередей. А MongoDb нашло свое место в системах статистики и сбора информации, где есть много операций вставки или обновления данных.

NoSQL решения характеризуются более быстрой реакцией, нежели традиицонные СУБД. Большинство NoSQL решений хорошо масштабируются.

Как выдержать миллионы запросов

Если проект расчитан на очень большое количество посещений, имеет миллионы пользователей, товаров или иного контента, то архитектура должна быть отличной от вышеописанных. Если в случае большого количества (миллионы) запросов, их можно раскидать на множество WEB-серверов, то с огромным объемом данных возникают архитектурные трудности. Схемы репликации не всегда применимы, так как данные физически не умещаются на одном сервере. В этом случае могут использоваться либо масштабируемые NoSQL решения, типа HBase или Google BigTable, либо схемы шардинга на классических РСУБД, типа mysql или postgesql.
6.jpg

NoSQL решения лучше применять, если в проектах с более простой логикой. Нас будет интересовать архитектура шардинга: - это когда данные одной таблицы РСУБД распределяются на множество серверов БД. При этом, одна таблица расшаривается по одному из столбцов. Применительно к социальным сетям – это user_id: все данные для пользователей с user_id от 1 до 10 млн расположены на одном сервере, записи с user_id от 10 до 20 млн расположены на другом сервере, а записи с user_id от 20 до 30 млн расположены на третьем сервере, и т.д.

Какие плюсы при таком подходе? При извлечении данных сканируются таблицы и индексы более мелких размеров, соответственно сервером БД выделяются более мелкие буфера. Соответственно, освободившиеся память может быть выделена под другие поисковые операции. В результате, поиск происходит быстрее и за одно и тоже время на этом же объеме оперативной памяти можно обработать больше запросов.

Из минусов можно отметить, что мы не сможем выполнять сложные запросы – JOIN запросы с несколькими таблицами. Для реализации логики, где необходимв выборка из объединения нескольких таблиц, используются бэкграундовские процессы. Как правило, для этих задач выделяется отдельный «скриптовый» сервер.

Возникает вопрос, а как бэкграундовские сервера получают информацию, что им необходимо сделать? В этом случае используются специализированные сервера распределения задач, например в LiveJournal использует Gaerman [4], или сервера очередей: RabbitMQ[5], ActiveMQ[6], RestMq [7] и тд.
7.jpg

Web Приложение, принимает из браузера Пользователя запрос, формирует необходимые данные и кладет их в очередь. На «скриптовом сервере» постоянно «живет» демонический скрипт, который постоянно, например с задержкой в 1 миллисекунду секунду, читает данные из очереди и выполняет соответствующую задачу.

Одну очоредь могут читать несколько скриптов обработки задач. Альтернативным вариантом является использования несколько очередей, каждая под свою задачу, а на каждый класс задач выделен соответствующий сервер: сервер конвертации видео, сервер конвертации графики, сервер сообщений, сервер репликации данных и пр. Если уведомление WEB-клиента не требуется, то скрипт обработки переходит к следующей задачи.

На рис 3 показано разбиение одной таблицы для 30 миллионов: Пользователей на три, по 10 млн на сервер БД. Реально же, разбиение происходит на более мелкие части, где-то по 100 тыс.

Для уведомления Пользователя, о том, что процесс завершился, например сконвертировалось видео или закачалась фотография, используется система уведомлений. В этом случае используется AJAX опрос. WEB клиент (браузер Пользователя), должен периодически опрашивать статус задачи, который хранится в memcached. Доступ к флагу можно организовать не задействуя WEB-Приложение, а выдавать напрямую из memcached через WEB сервер, используя модуль ngx_memcached, который входит в основной дистрибутив nginx.

Одна из самых распространенных в WEB задач – это задачи авторизации Пользователя. При использовании архитектуры шардинга, данная задача превращается в довольно-таки нетривиальную. Вся сложность состоит в том, что по логину и паролю (хешу пароля) необходимо просканировать все сервера БД. Как упоминалось выше: шардинг – это распределение одной большой таблицы на множество маленьких, каждая из которых хранится на отдельном сервере. В современных больших социальных сетях (VK, Facebook) их число измеряется сотнями.

Конечно же так не делается. Для этого используются NoSQL хранилища данных key/value типа: memcachedb, membase, redis, tarantool, Tokyo Tyrant и др.

Данные о Пользователе: ключ – логин, а в значении часть профиля Пользователя в json формате: хеш пароля, имя, возраст, пол. Tarantool, например, эти данные может хранить в отдельных полях, а в VK под эти цели разработана собственная БД. Оперативный доступ к данным Пользователя необходим не только при решении задачи авторизации, но и при отображении списка друзей или статуса активности других Пользователей.

Сам процесс авторизации проходит вообще без обращения к СУБД. В случае успеха в сессию кладется признак авторизации и номер сервера БД, где хранятся данные Пользователя. Отдельно поговорим о сессиях. Так как, обработка входных WEB запросов распылена на множество WEB серверов, даже используя keepalive соединение нет гарантии, что один и тот же WEB сервер будет постоянно обрабатывать все Ваши входящие запросы. По этому, для хранения сессий должно быть организовано отдельное централизованное хранилище, типа memcached или redis. В mail.ru, например, для этих целей используют tarantool.

Весь пользовательский контент: видео, музыка, фотографии хранится на отдельных серверах (storage), оптимизированных под отдачу статики. Вся информация о файлах, расположенных на storage-серверах, так же хранится по принципу шардинга, только в качестве меры разбиения используется не user_id,а content_id.

Номер storage-сервера, куда должен «заливаться» контент определеляется по заранее определенному конфигу или алгоритму: все четные заливки идут на сервер А, а нечетные на сервер B. Сам номер последнего залитого id, хранится в memcache c дублированием на внешнем источнике, в случае падения одного из серверов.

Общая схема «заливки» контента изображена на рис.
8.jpg

Web клиент (браузер пользователя), закачивает контент на WEB сервер. Web сервер, как правило по webdav или ftp передает контент на сервер конвертации и кладет данные о конвертировании в очередь 3. Сервер конвертации забирает данные из очереди и запускает задачу на конвертацию контента. В процессе выполнения конвертации данные о статусе поступают в memcached . Браузер пользователя средствами AJAX постоянно опрашивает статус выполнения задачи

По окончании конвертации, сконвертированный контент по webdav поступают на соответствующий storage-сервер 5, а данные о нем на соответствующий сервер СУБД 6. Статус окончания задачи поступает в memcached – 7. Браузер пользователя, получив статус окончания конвертации, перестает опрашивать memcached и запускает JS на отображение контента.

При вышеописанной архитектуре большое количество фоновых скриптов работает на множесте серверах. Как отследить их работоспособность?

Одно из используемых средств мониторинга - pinba . Данный продукт разрабатывался под PHP, как наиболее популярный язык для разработки WEB приложений. Pinba состоит из двух частей: непосредственно самого мониторинга, реализованного как php-расширение, и MySQL плагина, который осуществляет прием и агрегацию статистической информации. В качестве протокола обмена между средством замера и агрегирующим сервером используется protobuf, по этому, клиент не трудно реализовать на любом из популярных в WEB языков: java, python и возможно мониторить не только php-скрипты.

Дополнительно на одном из “скриптовых” серверов запускается скрипт мониторинга. Данный скрипт имеет “карту скриптов” – некую таблицу, более расширенную, нежели crontab: имя скрипта, кол-во запущенных копий, кол-во обработанных задач и средее кол-во возможно выполненных задач за последний промежуток времени. Мы постоянно имеем актуальную информацию о том, какие из задач запущены, сколько копий, какие из них в работе, а какие простаивают, какова длинна обработанных/не обработанных очередей. Исходя из этой информации, мы имеем полную информацию не только о работоспособности скриптов, но и более подробную информацию о загрузке системы, используя которую можно перекидывать часть ресурсов с одного сервера на другой.

Другой проблемой эксплуатации является синхронное распространение новых версий. Тут общего рецепта нет. В Facebook, например, для распространения новых исходников используется протокол bit-torrent. Как правило, используются специальные shell deployment скрипты.

Данный скрипт выполняет следующие функции:

  1. закачивает пакет с сервера распространения (deployment server);
  2. распаковывает пакет в директорию www/, где #rev – это номер текущей ревизии;
  3. запускает скрипт на изменение структуры данных на серверах БД;
  4. сбрасывает текущий кеш опкода данных;
  5. при необходимости, сбрасывает текущий кеш справочних данных;
  6. при необходимости, генерятся на основе шаблонов локальные конфиги;
  7. создает symlink в конфигурационном файле WEB сервера на директорию www/;
  8. перезапускает WEB сервер.
Категория: 
The code has been tested and works

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.