Принцип адвоката Брофловски, или облачная балансировка нагрузки своими руками +11


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

South Park, серия 306, «Панда—сексуальное домогательство»

Smug Alert!


Не так давно наши коллеги рассказали на конференции HighLoad++ о решении задачи балансировки нагрузки в облаках Google и Amazon, а также DNS-балансировки с использованием сервиса gdnsd. Это отличное введение в тему, с которым стоит познакомиться всем, кого жизнь уже заставила завести несколько фронтендов. И практическое руководство, если вы вынуждены иметь дело с облачным хостингом.

К счастью, бывают случаи, когда вы можете позволить себе удовольствие работать с реальным оборудованием, а не с облаками. Автор этих строк обожает реальное оборудование и готов часами рассказывать про его плюсы:

  • Вас не грабят на трафике. Погигабайтная оплата трафика — любимая статья доходов облачных систем, избалованных вниманием стартапов. Жизнь «железных» провайдеров проходит в жесточайшей конкуренции за более прижимистого потребителя, и для них нормально предлагать большой пакет трафика бесплатно. Есть и «пакетные» облака, такие как Linode, однако в них вы будете ограничены мощностью предлагаемых инстансов и, скорее всего, с грустью обнаружите, что для постройки мало-мальски серьёзного сервиса они вам нужны в огромных количествах — и, таким образом, облако возьмёт с вас за трафик другим способом.

  • Вы можете предсказуемо докупать серверы. Например, описание лимитов AWS занимает три десятка страниц A4. Внезапно натыкаясь на каждый лимит, вы будете доказывать Амазону потребность в его увеличении, а Амазон будет решать, достойны ли вы этого. Челобитные мелких клиентов рассматриваются минимум 3 дня, чаще — неделю. Тем временем лучшие dedicated-провайдеры предоставляют железо сразу или на следующий день, их волнует только ваша аккуратность в оплате счетов и законопослушность.

  • Жизнь на «железе» заставляет вас использовать проверенный open source, а не фирменные сервисы с загадочными свойствами, которые вы не можете изменить, если они плохи, или починить, если они сломались. Эта проблема отлично раскрыта в двух последних разделах упомянутого доклада.

  • Некоторые штуки вообще нормально работают только на тщательно подобранном оборудовании. Хорошим примером является наша любимая СУБД Aerospike. Количество проблем с ней прямо пропорционально возрасту SSD-дисков, поэтому мы не просто требуем настоящие железные SSD, но ещё и совершенно новые. А переход на интерфейсы NVMe там, где это возможно, поднял наше аэроспайководческое хозяйство в экзосферу, снизив нагрузку впятеро. Пользователи Aerospike в облаках в этом месте могут только грустно улыбнуться и пойти передёргивать кластер, который опять рассыпался.

Многие dedicated-провайдеры научились объединять серверы в виртуальные сети, и расширение ферм в них не представляет проблемы. Популярное исключение — Hetzner, где по-прежнему нужно резервировать юниты и планировать место, но я надеюсь, что он тоже разродится умной коммутацией. А вот с балансировкой дела обстоят хуже.

Там, где вообще есть смысл обсуждать с провайдером балансировку, вам предложат современного потомка чего-то такого:



Железо это штучное, стоить оно будет, разумеется, оскорбительных денег, а для конфигурирования требовать специальных знаний.

И тут самое время вспомнить, что…

Chef, что у нас сегодня на обед?


Ваши фермы наверняка уже работают с применением одного из средств автоматизации, а это значит, что массовые изменения дёшевы. А в качестве HTTP-фронтенда с большой вероятностью используется nginx на тех же серверах, что и обслуживают приложение. Это позволяет легко построить схему балансировки «каждый с каждым» — каждый сервер будет балансером, и он же захостит приложение, отвечающее на запрос.



Конфигурируем пул серверов в gdnsd:

; Проверяем отдельно написанной командой, жив ли 
; сервер с таким IP-адресом
service_types => {
   adserver => {
      plugin => extmon,
      cmd => ["/usr/local/bin/check-adserver-node-for-gdnsd", "%%IPADDR%%"]
      down_thresh => 4,  ; Не ответил 4 раза на тест? Этот сервер лежит.
      ok_thresh => 1,    ; Хоть раз ответил нормально? Жив!
      interval => 20,    ; Проверяем каждые 20 секунд
      timeout => 5,      ; Тупку более 5 секунд считаем отсутствием ответа 
   } ; adserver
} ; service_types

plugins => {
   multifo => {
      ; Если живы менее 1/3 хостов, то DNS будет возвращать весь список
      ; серверов, потому что явно происхоит что-то не то — например, общая
      ; перегрузка приложения, и отключение «сломанных» только усугубляет
      ; ситуацию
      up_thresh => 0.3,
      adserver-eu => {
         service_types => adserver,
         www1-de => 192.168.93.1,
         www2-de => 192.168.93.2,
         www3-de => 192.168.93.3,
         www4-de => 192.168.93.4,
         www5-de => 192.168.93.5,
      } ; adserver-eu
   } ; multifo
} ; plugins

Используем полученную конфигурацию в файле DNS-зоны:

eu.adserver.sample. 60 DYNA multifo!adserver-eu

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

upstream adserver-eu {
    server localhost:8080 max_fails=5  fail_timeout=5s;
    server www1-de.adserver.sample:8080 max_fails=5  fail_timeout=5s;
    server www2-de.adserver.sample:8080 max_fails=5  fail_timeout=5s;
    server www3-de.adserver.sample:8080 max_fails=5  fail_timeout=5s;
    server www4-de.adserver.sample:8080 max_fails=5  fail_timeout=5s;
    server www5-de.adserver.sample:8080 max_fails=5  fail_timeout=5s;
    keepalive 1000;
}

Если в ротации больше 25 серверов, не забудьте разбить их на группы по 25 штук под единым именем и динамически выбирать в gdnsd синонимы (DYNC) вместо A-записей.

Список серверов при желании можно заполнять автоматически по данным gdnsd или системы автоматизации. Например, у нас в компании используется puppet, и специальный крон-скрипт поддерживает в актуальном состоянии списки серверов разных типов, зарегистрированных на пуппетмастере. Строка с localhost защищает от ситуации, когда список окажется пустым из-за ошибки — в этом случае каждый nginx будет обслуживать только свой фронтенд и катастрофы не произойдёт.

Зажигаем, пацаны, зажигаем!


Итак, что получилось:

  • Великолепная отказоустойчивость. Риски сводятся к сетевым (это решается распределением приложения по нескольким регионам с независимым электропитанием и сетью) и конфигурационным (никто не мешает вам запулить в конфигурацию nginx или gdnsd изменение, которое быстро всё сломает — и рецепты борьбы с этим тоже известны).

  • Проблемы «прогрева» пула и проблемы недостатка мощностей не существует. Ваше веб-приложение гарантированно умрёт от нагрузки первым.

  • Равномерный расход трафика и распределение сетевой нагрузки. Принять 5 Гбит/с трафика на 10 серверов с гигабитом? Нет проблем, только не забудьте увести трафик между балансерами и приложениями во внутреннюю сеть, а также убедиться, что провайдер не продаёт вам на эти 10 серверов коммутатор с 1 Гбит/с общего аплинка в интернет.

  • «Плавные» деплои. При использовании только DNS-балансировки мы сталкивались с тем, что многим нашим партнёрам (SSP) «рвало крышу» поочерёдное пропадание наших серверов из пула. Ситуация осложнялась тем, что наши Java-приложения при инициализации подгружают в память массу необходимых им данных и это занимает время. Перекрёстная балансировка позволила сделать процесс практически незаметным для другой стороны.

Обида мистера Прутика


За бесплатную балансировку нужно платить, и жертвой являются sticky-сессии. Тем не менее, бесплатный вариант nginx предлагает балансировку по хешам IP, а современные NoSQL-базы, такие как Aerospike, могут быть использованы как надёжное общее хранилище сессий с быстрым временем ответа, которое вы можете использовать в своих приложениях. Наконец, можно, хоть это и непатриотично, перейти на HAProxy, который умеет маршрутизовать пользователей на нескольких балансерах по единому правилу. В общем, когда нам понадобятся sticky-сессии, мы будем бороться за них имеющимися средствами.

Цифры


Сейчас каждый из наших 20-ядерных серверов обрабатывает до 15 000 запросов в секунду, что близко к практическому потолку нашего Java-приложения. По всем кластерам мы балансируем и обрабатываем в пике больше полумиллиона запросов в секунду, 5 Гбит/с входящего и 4 Гбит/с исходящего трафика, за исключением CDN. Да, специфика DSP — это превышение входящего над исходящим, аукционных предложений значительно больше, чем содержательных ответов на них.

Автор статьи — igors
-->


К сожалению, не доступен сервер mySQL