Балансеры и автовыбор: как это работает
«Автовыбор» звучит просто, а на деле это четыре разных уровня и минимум пять стратегий, которые оптимизируют разное. И одна из них, самая популярная, под ТСПУ предсказуемо ломается. Разберу, где живёт балансировка, чем стратегии отличаются и почему leastPing «работает пару минут, потом заглохает». Без конфигов.
Перейти к практике →Две задачи балансировки
Балансировка решает не одну задачу, а две сразу, и их полезно держать в голове раздельно:
- Раздать нагрузку — чтобы клиенты не толпились на одной ноде, пока другие простаивают.
- Пережить падение — чтобы блок или смерть одной ноды не уронили сервис.
Разные механизмы решают эти задачи по-разному, и «автовыбор» на клиенте — только один из уровней. Всего их четыре, от клиента до транспортного фронта.
Четыре уровня
Уровень 1 — Xray-балансеры (серверные). Внутри одного Xray несколько выходных аутбаундов собираются в пул, и правило роутинга шлёт трафик не на конкретный outbound, а в балансер, который сам выбирает члена пула. Это то, что делает «нода веером на несколько выходов».
Уровень 2 — клиентский балансер через подписку. В подписку кладётся несколько серверов, и клиент сам тестирует их и выбирает быстрейший (канон — sing-box urltest, у Hiddify это «Auto»). Минус: бесшовного failover посреди соединения нет — при обрыве клиент перетестирует и переподключится.
Уровень 3 — транспортный фронт (HAProxy/nginx). L4-балансер перед нодами, который маршрутизирует по SNI, не расшифровывая TLS (Reality остаётся целым). Самый надёжный для коммерции. Важное ограничение: по SNI так балансируется только TCP — Hysteria2 (QUIC/UDP) этим способом не раскидать.
Уровень 4 — DNS round-robin / GeoDNS. Один домен → несколько A-записей. Работает для любого протокола, но грубо: нет проверки здоровья (мёртвая нода висит в ротации до правки DNS), а DNS вдобавок спуфят/блокируют. Только как крайний случай и грубое гео-направление, не как failover.
Четыре стратегии Xray-балансера
Внутри серверного балансера выбор члена пула определяет стратегия, и их четыре:
- random — случайно. Дефолт, годится для однородных нод.
- roundRobin — по кругу, поровну.
- leastPing — наименьший пинг. Нужен наблюдатель (observatory), который периодически пингует членов пула.
- leastLoad — стабильнейший под нагрузкой. Смотрит не на одну пробу, а на распределение задержек (baselines).
Разница между двумя последними — не косметика, а корень главной проблемы всех «автовыборов».
Почему leastPing «работает → заглохает»
Это самая частая жалоба, и она не случайна, а заложена в конструкцию. Разбираю по шагам, потому что понимание тут стоит дороже любого готового конфига:
- leastPing выбирает член пула с минимальным пингом. В пуле обычно есть голый raw-TCP+Reality+Vision — у него минимальный фрейминг, значит минимальный пинг → leastPing всегда выбирает именно его.
- ТСПУ по этому транспорту душит полосу — не рвёт коннект, а зажимает скорость почти в ноль.
- А наблюдатель пингует крошечный
generate_204раз в несколько десятков секунд — и эта мелкая проба проходит даже на задушенном канале. Для балансера член выглядит здоровым. - Итог: leastPing никогда не понижает этот раздавленный raw-член, потому что по пробе он «быстрый». Реальная скорость — ноль. «Работает → заглохает».
- Перезапуск приложения помогает случайно: новый коннект садится на ещё живой транспорт.
Замер это подтверждает: один и тот же ключ, серия проб connect→speedtest→hold — у vision-on-raw около трети удачных, у gRPC почти все. Отсюда две мысли, которые лечат балансер.
Что с этим делать (идеи, не команды)
- Убрать raw+Vision из пула — оставить gRPC/xHTTP-члены. raw переживает блок хуже всех.
- leastLoad вместо leastPing — он смотрит на распределение задержек, а не на мелкую пробу, и раскидывает шире, не залипая на одном раздавленном члене.
- Прямые ноды в дефолтном пуле, каскад — в резерв. Каскад душит upload; для основного пула быстрее прямые ноды, каскад держат как обход/fallback.
- Блок QUIC перед правилом балансера, иначе видео залипает в туннеле.
Что выбрать под VPN-сервис
Стратегии оптимизируют разное, и универсальной нет:
- Failover (HAProxy/nginx
backup) — про аптайм: основные ноды плюс горячий резерв, с проверкой здоровья. - Least-conn — про длинные сессии: у VPN соединения долгие, round-robin перегрузит «счастливчика», а least-conn раздаёт по числу активных.
- Least-ping — про скорость для юзера в мультирегионе, но с оговоркой про залипание выше.
- Least-load — про стабильность под нагрузкой и всплесками на разнокалиберных нодах.
- Source-hash — про липкость: держит TCP и UDP одного клиента на одной ноде.
Рабочая связка для коммерции: фронт HAProxy/nginx по SNI + least-conn + backup-ноды (failover и длинные сессии), сверху клиентский urltest (юзер берёт быстрейший регион), а Xray leastLoad — когда одна нода веером уходит на несколько выходов.
Про здоровье нод
Одна ловушка, которую надо знать заранее: серверный observatory пингует с самой ноды, а нода может быть жива в мире, но зарезана для российских клиентов. Такую проблему observatory не увидит. Значит проверять здоровье надо из РФ, отдельным внешним воркером, а не только глобально. Это отдельная тема — вынесена в практику про healthcheck.
Дальше — в практике: как собрать боевой leastPing/leastLoad автовыбор, как задаётся пул тегами хостов и главные грабли доставки шаблона. Пошагово — в статье «Автовыбор leastPing: собираем».
Следующий гайд Автовыбор leastPing: собираем → ↗ Не понравилась статья или что-то непонятно? Напишите мне — помогу или поправлю. @notrealvpn →