独立站负载均衡:多实例部署、健康检查、会话保持与故障转移

独立站上负载均衡的触发点是日访问量稳定超过5万、单台4核8G CPU长期60%以上,或者你已经吃过一次"服务器挂了全站打不开"的亏。合格标准是:至少2个应...

独立站负载均衡:多实例、健康检查与故障转移Load balancing: multi-instance, health check, failover 反直觉:会话保持不是必须的,无状态化才能真正横向扩展Counter-intuitive: sticky sessions hurt scaling; go stateless 负载均衡器 LBLoad Balancer L4 TCP / L7 HTTPL4 TCP / L7 HTTP 应用实例 AApp Instance A 健康 200 · 权重 50%Healthy, weight 50% 应用实例 BApp Instance B 健康 200 · 权重 50%Healthy, weight 50% 应用实例 CApp Instance C 3次失败 · 自动摘除Unhealthy, drained 健康检查:每10秒请求一次 /health,连续3次失败摘除,连续2次成功恢复Health: GET /health every 10s; 3 fails out, 2 oks in 会话保持:默认关闭,登录态放Redis或JWT;只有老系统实在改不动才开cookie粘性Sticky off; sessions in Redis/JWT 故障转移:单台宕机LB在10秒内摘除,流量自动打到健康实例,用户无感知Failover: LB drains dead node in 10s, user sees nothing 至少跨2台不同物理机/可用区;同机房单机断电=白配Spread across AZs, not one rack
Балансировка нагрузки: рабочие экземпляры принимают трафик, отказавшие автоматически исключаются

独立站负载均衡:多实例部署、健康检查、会话保持与故障转移

Сначала вывод: 独立站上负载均衡的触发点是日访问量稳定超过5万、单台4核8G CPU长期60%以上,或者你已经吃过一次”服务器挂了全站打不开”的亏。合格标准是:至少2个应用实例跨可用区部署、每10秒一次健康检查、连续3次失败自动摘除、故障转移在10秒内完成。反直觉的一点是,会话保持(sticky session)不是必须开的——把登录态放到Redis或JWT里,让应用真正无状态,才是多实例扩展的前提。开了会话保持,一台机器挂了那台上的用户照样掉线。

1. Когда балансировка нагрузки нужна, а когда это избыточно

Балансировка нагрузки — не то, с чего стоит начинать. При трафике до 5000 визитов в день одного VPS 2 ядра / 4 ГБ с Nginx+PHP+MySQL вполне достаточно, а покупка LB за несколько сотен рублей лишь добавит сложности. Реальных сигналов к переходу на несколько экземпляров три: длительная загрузка CPU выше 60% на одной машине, простой при каждом релизе, потерянные заявки из-за отказа одной машины. Совпали два из них — тогда внедряйте LB.

独立站的典型升级路径是:单VPS跑compose(日访1万以内)→ 拆MySQL到独立机器(日访3万)→ 应用跑2台+云LB(日访5万)→ 应用3到5台+自动扩缩容(日访20万以上)。不要跳步。CDN在LB之前先扛住静态流量,源站压力能降一半,见 Глобальное ускорение CDN.

Этап Форма развёртывания Число экземпляров приложения Ориентир по трафику в день Прирост месячных затрат
Начальный этап Один VPS + compose 1 <10 000 0
Этап роста 1 экземпляр приложения + отдельная БД 1 10 000–50 000 +150 ₽
Этап стабильности 2 экземпляра приложения + облачный LB 2 50 000–200 000 +около 100 ₽ за LB
Пиковый период 3–5 экземпляров приложения + автомасштабирование 3–5 >200 000 +оплата по часам

二、L4还是L7:独立站选哪一层

负载均衡分四层(L4,按TCP/IP转发)和七层(L7,按HTTP路径转发)。L4性能高、配置简单,但只能按端口转发;L7能根据域名、路径、Header做路由,还能做灰度和HTTPS卸载。独立站选L7,因为你需要按路径分流:静态文件走CDN,API走应用,后台走另一组实例。

Выбор LB у облачных провайдеров: в AWS это ALB (Application Load Balancer), в Alibaba Cloud — SLB или ALB, в Tencent Cloud — CLB. Функционально они пересекаются, цены начинаются от 100–200 юаней в месяц. Простой критерий: если задача — просто «гонять трафик между двумя машинами по кругу», берите самый дешёвый LB четвёртого уровня; если нужно маршрутизировать по путям, делать канареечные релизы или распределять по доменам — берите LB седьмого уровня.

Параметр сравнения Балансировка L4 TCP Балансировка L7 HTTP
По чему распределяет IP + порт Домен / путь / Header / Cookie
Производительность Очень высокая, микросекунды Чуть ниже, миллисекунды
Разгрузка HTTPS Не поддерживается Поддерживается, сертификат на LB
Канареечный релиз Не поддерживается по доле трафика Поддерживается переключение по весам
独立站适用 Простое чередование двух машин Маршрутизация по путям, канареечные релизы
Ориентир по цене в месяц Около 80–120 юаней Около 150–250 юаней

III. Проверки здоровья: как настроить, чтобы не убить живые узлы

健康检查是LB的核心。配太松,挂掉的机器还在接流量;配太紧,应用刚启动慢一点就被误摘,导致雪崩。独立站的标准配置是:检查路径/health(只返回200,不查数据库,避免把DB慢传染到LB)、间隔10秒、连续3次失败才摘除、连续2次成功恢复。

Эндпоинт /health должен быть лёгким. Частая ошибка — заставить его проверять соединение с MySQL: при малейшем сбое базы все экземпляры приложения исключаются из LB, и весь сайт отдаёт 503. Правильно: /health возвращает только статус живости процесса, а здоровье базы проверяется отдельным эндпоинтом /health/db, который только мониторится и не влияет на решение об исключении. Пороги мониторинга и алертов см. в Мониторинг сайта и оповещения.

Параметр Рекомендуемое значение Пояснение Частая ошибка
Путь проверки GET /health Не трогает DB, возвращает только 200 Запрос к DB приводит к массовому исключению
Интервал проверки 10 секунд Баланс между чувствительностью и ложными срабатываниями 1 секунда — слишком агрессивно
Таймаут 5 секунд Превышение считается одной неудачей 1 секунда — слишком мало
Порог нездоровья 3 неудачи подряд Узел исключается Исключение после 1 неудачи
Здоровый порог 2 успеха подряд Возврат в пул Восстановление после 1 успеха
Код ответа 200 считается здоровым Другие коды считаются неудачей 503 считается здоровым

IV. Привязка сессий: включайте только при крайней необходимости

Многие, впервые запуская несколько экземпляров, сразу думают: «Пользователь залогинился на машине A, а следующий запрос попадёт на B — и его выкинет», и включают привязку сессий. Это экономит время сейчас, но создаёт долг на будущее. Проблема привязки в том, что при падении машины A все привязанные к ней пользователи разом теряют сессию, и смысл отказоустойчивости наполовину теряется.

Правильный подход — вынести сессии из памяти приложения. В PHP храните сессии в Redis, в Node используйте stateless-токены JWT, всё состояние входа — в одном общем хранилище. Тогда любой экземпляр приложения может обработать запрос любого пользователя, и падение любой машины не влияет на онлайн-пользователей. Сохранение сессий включайте только в двух случаях: старая система, которую нельзя переделать, или сторонний плагин, жёстко зависящий от локальных сессий.

Схема сессий Расширяемость Влияние сбоя Стоимость миграции Рекомендация
Session в локальных файлах Плохо, обязательна sticky-привязка Падение одной машины = пользователи отключены Низкая Не рекомендуется
Централизованная session в Redis Хорошо Незаметное переключение Средняя, достаточно поменять конфигурацию Рекомендуется
JWT без состояния Лучше всего Незаметное переключение Высокая, придётся переделать аутентификацию Рекомендуется для новых проектов
Привязка через cookie на LB Плохо Упадёт машина — упадёт соединение Низкая, достаточно включить Только как временное решение

5. Отказоустойчивость: как проверить, что LB действительно переключит трафик

Настроить LB — ещё не значит включить отказоустойчивость. Многие команды после запуска ни разу не убивали сервер вручную и узнают о проблеме только когда он падает по-настоящему: то health check на LB не настроен, то security group не пропускает трафик. Перед запуском обязательно проведите учения: в продакшене (или на стейдже) вручную остановите приложение A и посмотрите, переведёт ли LB трафик на B в течение 30 секунд и заметят ли это пользователи.

Ещё одна частая ошибка — два экземпляра приложения на одной физической машине или в одной стойке: отключение питания стойки убьёт оба сразу. Размещайте их минимум в двух зонах доступности (AZ) или хотя бы на двух разных хостах. Полная методика резервного копирования и восстановления описана в Бэкап и восстановление сайта.

Пример из практики: у одной B2B-компании WordPress крутился на одном VPS. Ночью на хосте отключили питание на время обслуживания, сайт лежал 4 часа, за это время потеряли 3 запроса от европейских клиентов. После этого добавили второй экземпляр приложения за облачным LB, перенесли сессии в Redis и разнесли по зонам доступности. В следующее окно обслуживания экземпляр B автоматически принял весь трафик, и ни клиенты, ни отдел продаж ничего не заметили. Лишние 300 рублей в месяц за экземпляр — ничто по сравнению с ценой потерянного запроса.

Сценарий учения Действия Ожидаемый результат Что делать, если не прошли
Убить процесс приложения systemctl stop app LB выводит из ротации за 30 секунд, трафик уходит на B Проверить путь health check
Отрезать сеть приложения Заблокировать порт через iptables Вывод из ротации за 10 секунд Проверить, что security group пропускает подсеть LB
Перезагрузка машины reboot После старта автоматически возвращается в ротацию Проверить скрипт запуска и health
Сбой базы данных Внедрить медленный запрос Приложение не выводится из ротации по ошибке health не должен обращаться к БД
Весь трафик на B Перевести вес 100 на B B держит нагрузку 5 минут в одиночку Проверить, выдержит ли B нагрузку

FAQ: частые вопросы

При какой посещаемости нужен балансировщик?
Абсолютной цифры нет, но если совпали два из трёх сигналов — пора: CPU на одном сервере 4 ядра / 8 ГБ стабильно выше 60%, релиз требует простоя, уже теряли запросы из-за отказа одной машины. Реальность независимых сайтов такова: до 50 000 визитов в день хватает одного сервера с CDN. Сначала подключите CDN и вынесите статику — нагрузка на origin упадёт вдвое, и часто несколько экземпляров вообще не нужны.
Нужно ли включать привязку сессий?
По умолчанию — нет. Перенесите сессии в Redis или перейдите на JWT, чтобы приложение стало без состояния: тогда любой экземпляр обработает любой запрос, а отказ одной машины пользователи не заметят. Со sticky session все пользователи на упавшей машине отключатся, и отказоустойчивость окажется бесполезной. Включать привязку через cookie стоит только временно, если старая система никак не может отказаться от локальных сессий.
Почему health check не должен обращаться к базе данных?
Дрожание базы данных передаётся на балансировщик. Если в /health выполняется запрос к MySQL и медленный запрос превышает 5 секунд, балансировщик признает приложение неработоспособным; когда все экземпляры приложения одновременно обращаются к БД, они все одновременно признаются неработоспособными — и весь сайт отдаёт 503. Правильный подход: /health возвращает только факт живости процесса, а здоровье БД выносится в отдельные метрики мониторинга и не участвует в решении балансировщика о выводе из ротации.
Можно ли разместить два экземпляра на одной физической машине?
Нет, это равносильно отсутствию отказоустойчивости. При отключении питания или сбое хоста на одной физической машине оба экземпляра упадут вместе. Нужно как минимум разместить их в двух зонах доступности (AZ) или как минимум на двух разных хостах. Облачные провайдеры обычно позволяют указать политику размещения на разных физических машинах при создании экземпляра. Если бюджет позволяет купить только два экземпляра, выбирайте разные зоны доступности.
Сколько стоит балансировщик у облачного провайдера в месяц?
L4大约每月80至120元,L7大约150至250元,另外按流量计费每GB约0.5元。独立站月流量通常几百GB,总LB费用控制在200元以内。AWS ALB稍贵,基础费约20美元/月+流量费。预算紧张可以用Nginx自建LB,月成本省下来,但要自己维护高可用。
Как проверить, что отказоустойчивость действительно работает?
Перед запуском проведите учения: на предпродакшене или в продакшене в часы низкой нагрузки вручную остановите процесс приложения A и непрерывно отправляйте запросы через curl на балансировщик, наблюдая, переключатся ли запросы на B без ошибок в течение 30 секунд. Затем проверьте, вернётся ли экземпляр в ротацию автоматически после перезапуска. Если учения не пройдены, не запускайте — при реальном сбое никто не даст вам 30 секунд на поиск ошибки.

В заключение

负载均衡对独立站的价值,一半是扛流量,另一半是扛故障。前者很多人能算清,后者常被忽略——多一台应用实例的成本,换来的是”一台机器挂了用户无感”,这在B2B询盘场景里就是钱。

Три шага внедрения: первый — сделать приложение без состояния, вынести сессии в Redis; второй — поднять второй экземпляр, подключить его к облачному балансировщику и настроить проверку здоровья; третий — провести учения с остановкой процесса и убедиться, что трафик переключается в течение 30 секунд. После этих трёх шагов архитектура с несколькими экземплярами действительно становится работоспособной. Сопутствующий мониторинг и оповещения см.Мониторинг сайта и оповещения, продвинутая настройка автомасштабирования — см.Автомасштабирование.

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

crater
crater Эксперт Crater

Официальный аккаунт организации · crater Crater

环形山 (Crater) — компания, которая помогает выходить на зарубежные рынки: разработка сайтов на WordPress, Google SEO и комплексный рост в GEO. Мы работаем с умными устройствами, промышленным оборудованием, SaaS и новой энергетикой.

Возможности продуктаБелая книга по методологииОтраслевые отчёты
965篇分享
78статей в базе знаний