Веб-сокеты с балансировкой нагрузки


105

У меня вопрос, как балансировать нагрузку на веб-сокеты.

У меня есть сервер, поддерживающий веб-сокеты. Браузеры подключаются к моему сайту, и каждый открывает веб-сокет для www.mydomain.com. Таким образом, мое приложение в социальной сети может отправлять сообщения клиентам.

Традиционно, используя только HTTP-запросы, я увеличивал масштаб, добавляя второй сервер и балансировщик нагрузки перед двумя веб-серверами.

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

Итак, как мне -

  1. заставить клиента подключаться напрямую к веб-серверу (а не к балансировщику нагрузки) при загрузке страницы? Могу ли я просто загружать JavaScript из узла, а балансировщики нагрузки (или что-то еще) случайным образом изменяют URL-адрес сценария каждый раз, когда страница изначально запрашивается?

  2. справиться с волнистым началом? Браузер заметит, что соединение закрывается, когда веб-сервер завершает работу. Я могу написать код JavaScript, чтобы попытаться повторно открыть соединение, но узел на какое-то время исчезнет. Итак, я думаю, мне придется вернуться к балансировщику нагрузки, чтобы запросить адрес следующего узла, который будет использоваться?

  3. Мне было интересно узнать, как балансировщики нагрузки отправляют перенаправление при первоначальном запросе, так что браузер изначально запрашивает www.mydomain.comи перенаправляется на www34.mydomain.com. Это работает достаточно хорошо, пока узел не выйдет из строя - а сайты вроде Facebook этого не делают. Как они это делают?


1
Вы можете балансировать нагрузку на сетевом уровне, как предлагается здесь
Крис Сноу,

1
Существуют также альтернативные подходы, такие как балансировка нагрузки на основе DNS или использование сервера оркестрации на основе http. Я попытался суммировать плюсы и минусы каждого подхода на deepstream.io/blog/load-balancing-websocket-connections
wolframhempel

@wolframhempel Ссылка мертва. :-(
Эмиль Кормье

Ответы:


95

Поместите балансировщик нагрузки L3, который распределяет IP-пакеты на основе хэша IP-порта источника на ферму серверов WebSocket. Поскольку балансировщик L3 не поддерживает состояние (с использованием хешированного IP-порта источника), он будет масштабироваться в соответствии со скоростью передачи на низком уровне оборудования (например, 10GbE). Поскольку распределение является детерминированным (с использованием хешированного исходного IP-порта), оно будет работать с TCP (и, следовательно, с WebSocket).

Также обратите внимание, что жесткое ограничение в 64 КБ применяется только к исходящему TCP / IP для данного (исходного) IP-адреса. Это не относится к входящему TCP / IP. Мы протестировали Autobahn (высокопроизводительный сервер WebSocket) с 200 тыс. Активных подключений на 2-ядерной виртуальной машине с 4 ГБ ОЗУ.

Также обратите внимание, что вы можете выполнить балансировку нагрузки L7 на пути HTTP, объявленном во время первоначального рукопожатия WebSocket. В этом случае балансировщик нагрузки должен поддерживать состояние (какая пара исходных IP-портов к какому внутреннему узлу идет). Тем не менее, при хорошей настройке он, вероятно, будет масштабироваться до миллионов соединений.

Отказ от ответственности: я являюсь первоначальным автором Autobahn и работаю на Tavendo.


Поэтому я бы загрузил свою библиотеку javascript из URL-адреса балансировщика нагрузки и дал URL-адрес балансировщика нагрузки при создании веб-сокета в javascript - вы имеете в виду, что он прозрачен для браузера? Это круто!
Джон Смит

1
Да, существует только 1 URL-адрес, и имя хоста последнего должно соответствовать вашему балансировщику нагрузки. Внутренний сервер WebSocket имеет внутренние IP-адреса (не общедоступные) и может работать на портах, отличных от общедоступного. Единственное предостережение заключается в том, что вам может потребоваться сообщить серверам WebSocket их общедоступное видимое имя хоста, IP и порт, поскольку соответствующие серверы WebSocket будут проверять, что URL-адрес, указанный в HTTP-заголовке рукопожатия WS, соответствует имени хоста / ip / порту, который они слушают.
оберстет

У меня не так много соединений с веб-сокетами для балансировки, но у меня много трафика в одном или, скажем, очень мало соединений. для простоты скажем теперь одно соединение, как я могу сбалансировать запросы, проходящие через одно соединение веб-сокета?
user1870400

Когда я делаю больше 5000 соединений в java websocket, он не освобождает память .... есть ли какое-нибудь решение?
Пунам Патель

3

Обратите внимание, что если логика вашего сервера websocket работает на nodejs с socket.io, вы можете указать socket.io использовать общее хранилище ключей / значений redis для синхронизации. Таким образом, вам даже не нужно заботиться о балансировщике нагрузки, события будут распространяться между экземплярами сервера.

var io = require('socket.io')(3000);
var redis = require('socket.io-redis'); 
io.adapter(redis({ host: 'localhost', port: 6379 }));

См .: http://socket.io/docs/using-multiple-nodes/

Но в какой-то момент я думаю, что Redis может стать узким местом ...


2

Вы также можете достичь балансировки нагрузки уровня 7 с помощью проверки и «функциональности маршрутизации».

См. «Как проверять и балансировать трафик WebSockets с помощью Stingray Traffic Manager, и, при необходимости, как управлять WebSockets и HTTP-трафиком, получаемым на один и тот же IP-адрес и порт». https://splash.riverbed.com/docs/DOC-1451


2
Мне пришлось провести некоторое расследование, чтобы найти информацию, которую вы связали. Обратный автомат помог мне найти живую копию этой статьи: community.pulsesecure.net/t5/Pulse-Secure-vADC/…
Вик,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.