Ваш сайт или другой проект приносит деньги только тогда, когда он работает.
Нельзя просто выложить код на серверы, залить схему в базу данных и делегировать домен.
Будем говорить о планировании отказоустойчивости и мониторинге проектов:
- оцениваем риски отказа различных компонентов;
- какие-то из вероятных проблем просто мониторим и планируем действия при сбоях;
- проблемы, которых можно избежать легко и дешево, закрываем сразу.
Расскажу на примерах о том, что всё всегда ломается, но с этим можно жить.
2. Постановка задачи
• У нас есть сайт, он приносит нам деньги
• Если он не работает — мы несем убытки
• У нас есть небольшой бюджет на отказоустойчивость + мозг
3. Всему есть предел
• Датацентры:
• Tier I: 99.671% (142 минуты в месяц)
• Tier II: 99.749% (~109 минут в месяц)
• Tier III: 99.982% (~8 минут в месяц)
• Tier IV: 99.995% (~2 минуты в месяц)
• Допустим, мы стоим в TIER III и закладываться на падение ДЦ
пока не будем
4. Реальность
• Найти ДЦ “без единого разрыва” не сильно сложно
• А железо ломается постоянно
• Софт — тем более
• Свой софт — ещё чаще
5. Дано
• У нас есть сервер за 20000р/месяц
• На нем:
• Nginx (фронтенд)
• Наше приложение (бэкенд)
• Memcached
• База данных
• Очередь задач
• Наши обработчики задач из очереди
9. Фронтенд: что может произойти
• Сломалась железка
• Умер сервис (crash, oom killer, всякое бывает)
• Тупит сервер, сайт тормозит
10. Фронтенд: балансировка
• Обычно frontend – stateless, можем поставить несколько
(защитимся от вылета железа + некоторых софтовых проблем)
• Нужно обеспечить отказоустойчивость, масштабируемость
• Как правило, уровень выше – не наша зона ответственности
11. Фронтенд: балансировка
• DNS round robin: не знает, работает ли конкретный сервер
• Shared IP: VRRP, CARP (active + N passive, нужно отдельно
дорабатывать переключение при проблемах с сервисами)
• DNS round robin между shared ips
12. Фронтенд: балансировка
Если есть L3 железка перед фронтендами:
• Cisco: равнозначные статические маршруты + IP SLA check
• Juniper: равнозначные статические маршруты + BFDd + monit
13. Фронтенд: балансировка
ip sla 1
tcp-connect 1.1.1.10 80 source-ip 1.1.1.1 control disable
timeout 900 threshold 1000 tag front1 frequency 1
ip sla schedule 1 life forever start-time now
track 1 ip sla 1 reachability
ip sla 2
tcp-connect 1.1.1.20 80 source-ip 1.1.1.1 control disable
timeout 900 threshold 1000 tag front2 frequency 1
ip sla schedule 2 life forever start-time now
track 2 ip sla 2 reachability
mls ip cef load-sharing full
ip route 1.1.1.100 255.255.255.255 1.1.1.10 track 1
ip route 1.1.1.100 255.255.255.255 1.1.1.20 track 2
16. Фронтенд: мониторинг
• Critical: http-5xx > N в секунду
• Critical: медленных запросов (> 1s) > M %
N, M на ваш вкус, обычно для сайта с 200+ RPS:
• N = 10 RPS
• M = 5 %
17. Фронтенд: что может произойти
• Сломалась железка
• Умер сервис (crash, oom killer, всякое бывает)
• Тупит сервер, сайт тормозит – мониторинг
18. Бэкенд
• Получает данные из БД, других сервисов
• Производит вычисления над данными (шаблонизация, ...)
• Отдает пользователю ответ
19. Бэкенд: что может произойти
• Сломалась железка
• Умер сервис (crash, oom killer, всякое бывает)
• Проблемы с БД (совсем умерло, тупит, ошибки)
• Проблемы с другими внешними ресурсами
• Тормоза из-за нехватки ресурсов, кривого кода
• Тормоза из-за бОльшего количества запросов
20. Бэкенд
• Не храним на бэкенде данные, иначе сложная балансировка,
проблемы при отказе (сессии на локальном диске, и т.д.)
• Ставим несколько железок, балансировка на фронтенде
21. Бэкенд
• Выясняем, сколько запросов одновременно бэкенд может
обслужить, больше не берем (HTTP-503)
• Фронтенд может в этом случае отправить запрос соседу
• Определяемся со временем ответа, ставим правильные
таймауты на фронтенде
22. Бэкенд: балансировка
• proxy_connect_timeout 10ms; #для локалки
• proxy_read_timeout 500ms; #настраиваем под себя
• proxy_next_upstream error timeout invalid_header http_502
http_503 http_504;
• proxy_next_upstream_tries 2;
* Nginx 1.9.13+ не будет ретраить POST
23. Бэкенд: мониторинг
• Живость сервиса (есть процесс, listen socket, отвечает на /status)
• Потребление ресурсов процессом (cpu, mem, swap io, disk io, open
fd)
• Runtime специфичные метрики (GC, heap, размер кэшей, …)
24. Бэкенд: мониторинг
• Количество принятых и обработанных запросов (лог, statsd)
• Количество ошибок (можно снимать на фронтенде)
• Время ответа (лог, statsd, можно снимать на фронтенде)
• Работа с БД или сервисами (количество запросов, ошибок,
время ответа)
• Время, потраченное на вычисления
27. Бэкенд: что может произойти
• Сломалась железка
• Умер сервис (crash, oom killer, всякое бывает)
• Проблемы с БД (совсем умерло, тупит, ошибки) - мониторинг
• Проблемы с другими внешними ресурсами - мониторинг
• Тормоза из-за нехватки ресурсов, кривого кода - мониторинг
• Тормоза из-за бОльшего количества запросов
29. БД: что может произойти
• Сломалась железка
• Потеря данных из-за железа, DELETE, …
• Умер сервис (crash, oom killer, всякое бывает)
• Тормоза из-за нехватки ресурсов
• Тормоза из-за бОльшего количества запросов
• Тормоза из-за кривых запросов (нет нужного индекса, …)
30. БД: master-slave
• Настраиваем репликацию на другой сервер
• Основная нагрузка большинства проектов – чтение, можно
работать в read-only режиме при отказе мастера
31. БД: master-slave
• На реплику можем отправить все SELECTы, которые не
чувствительны к replication lag
• Для таких запросов можно приложению дать отдельный endpoint
– балансировщик, который распределит соединения между
master и репликами (TCP)
• Или научить приложение работать с несколькими серверами
сразу – сможете контролировать таймауты, делать retry на другой
сервер в случае проблем
32. БД: переключение мастера
• Принимаем решение о переключении (может, быстрее починить
сервер?)
• Переключаем запись на реплику (будут ошибки)
• Если нужно, ждем, пока долетят изменения
• Добиваем текущий мастер
• Перенастраиваем slave->master
• Если есть ещё реплики, переключаем их на новый master
33. БД: переключение мастера
• Переключаться на автомате сложно и стрёмно
• Лучше минимизировать риски и взять под мастер БД более
надежное железо (raid, БП и т.д.)
• Пишем инструкцию, как переключить мастер (по шагам, с
хорошей детализацией, чтобы включать мозг по минимуму)
• Устраиваем учения и тестируем инструкцию, замеряем время
простоя
• Дополняем и уточняем инструкцию, пытаемся сократить время
простоя
• Тестируем снова
34. БД: репликация != бэкап
• “DELETE from table” – убьет данные на реплике тоже
• Регулярно делаем бэкап + копируем WAL
• Можно держать реплику, специально отстающую на N минут
(чтобы быстро отключить репликацию и успеть спасти данные)
• Бэкап лучше копировать в другой ДЦ тоже
35. БД: мониторинг
• Живость сервиса (есть процесс, listen socket)
• Потребление ресурсов процессом (cpu, mem, swap io, disk io, open
fd)
• Какие запросы занимают CPU
• Какие запросы нагружают диски
• Отставание репликации, трафик репликации
• Поток запросов (больше, меньше, как обычно)
• Мониторинг наличия бэкапа
38. БД: что может произойти
• Сломалась железка
• Потеря данных из-за железа, DELETE, … мониторинг + инструкция
по ручному вмешательству
• Умер сервис (crash, oom killer, всякое бывает)
• Тормоза из-за нехватки ресурсов - мониторинг
• Тормоза из-за бОльшего количества запросов - мониторинг
• Тормоза из-за кривых запросов (нет нужного индекса, …) -
мониторинг
40. Memcached: что может произойти
• Сломалась железка
• Умер сервис (crash, oom killer, всякое бывает)
• Тормозит сеть
• Тормоза из-за нехватки ресурсов
41. Memcached
• Ставим несколько
• Клиенты умеют ходить сразу во все (шардинг)
• Обязательно настраиваем таймауты
• Проверяем логику инвалидации (expire все равно ставим)
42. Memcached
• Выдержит ли БД, если почистить все кэши?
• А должна
• Сколько нужно прогретых кэшей, чтобы сайт работал?
• Проверяем, как клиент будет перераспределять данные и
запросы (решардинг), чтобы вылет 1 сервера не испортил нам все
• Эффективен ли кэш?
• Может, его выкинуть?
44. Memcached: что может произойти
• Сломалась железка
• Умер сервис (crash, oom killer, всякое бывает)
• Тормозит сеть – мониторинг на стороне бэкенда
• Тормоза из-за нехватки ресурсов – мониторинг
45. Message Queue
• Хранит задачи для отложенной обработки
• Publisher – записывает сообщение в очередь
• Consumer – получает сообщения и выполняет работу
46. Message Queue: что может произойти
• Сломалась железка
• Потеря данных (умерла железка с необработанной очередью)
• Умер сервис (crash, oom killer, всякое бывает)
• Умерли все обработчики (копятся сообщения)
• Тормоза из-за нехватки ресурсов
47. Message Queue
• Некоторые брокеры заявляют о кластерном режиме работы (мне
не очень нравится, много вопросов)
• Можно поставить несколько брокеров: писать в любой живой,
обработчики должны выбирать сообщения из всех
• Обязательно настраиваем таймауты
48. Message Queue: очень важные сообщения
• Пишем одно и то же сообщение в несколько брокеров, убираем
дубли на уровне обработчиков
• Или имеем механизм проверки целостности и восстановления
состояния по другим источникам (БД)
52. Message Queue: что может произойти
• Сломалась железка
• Потеря данных (умерла железка с необработанной очередью)
• Умер сервис (crash, oom killer, всякое бывает)
• Умерли все обработчики (копятся сообщения) - мониторинг
• Тормоза из-за нехватки ресурсов - мониторинг
53. Цена вопроса
• Начали с 1 dedicated сервера за 20тр/месяц
• Минимум: ставим еще один такой же (40тр)
• Норма: 2+ БД отдельно на хорошем железе, все остальное
размазано по 2+ серверам
54. А что в “облаках”?
• Есть возможность поднять новую машину за N минут + API
• Есть готовые балансировщики
• Есть готовые MQ сервисы
• Ресурсы дороже
• Можно нарваться на latency (сеть, диск), недополучить ресурсов
(cpu)
• Готовые сервисы – черные ящики для вас
55. Резервный ДЦ
• Данные (репликация)
• Актуальная конфигурация ПО
• Актуальные версии вашего софта
• План переключения трафика в резервный ДЦ:
• DNS (помним про ttl)
• PI адреса + BGP
56. Самое главное
• Составьте список возможных отказов
• Исключайте (закрывайте) простые
• Если сценарий сложный:
• уменьшаем вероятность
• закрываем часть
• мониторинг + план на ручное вмешательство
• Главное – иметь план действий, всё остальное — оптимизация