Проксирование WebSockets с балансировщиком нагрузки TCP без липких сессий

Я хочу прокси-соединения WebSocket с несколькими серверами node.js, используя Amazon Elastic Load Balancer. Поскольку Amazon ELB не обеспечивает реальной поддержки WebSocket, мне нужно использовать его обычные TCP-сообщения. Тем не менее, я пытаюсь понять, как это будет работать без какой-либо липкой функциональности сессии.

Я понимаю, что WebSocket s сначала отправляет запрос HTTP Upgrade от клиента, который обрабатывается сервером путем отправки ответа, который правильно обрабатывает проверку подлинности ключа. После того как сервер отправит этот ответ и он будет одобрен клиентом, между этим клиентом и сервером существует двунаправленное соединение.

Однако, допустим, клиент после утверждения ответа сервера отправляет данные на сервер. Если он отправляет данные на балансировщик нагрузки, а затем балансировщик нагрузки передает эти данные на другой сервер, который не обработал исходный запрос на обновление WebSocket, то как этот новый сервер узнает о соединении WebSocket? Или клиент будет автоматически обходить балансировщик нагрузки и отправлять данные непосредственно на сервер, который обработал первоначальное обновление?

2 ответа

Решение

Я думаю, что нам нужно понять, чтобы ответить на этот вопрос, как именно базовое TCP-соединение развивается в течение всего процесса создания WebSocket. Вы поймете, что " липкой" частью соединения WebSocket является само лежащее в основе TCP-соединение. Я не уверен, что вы имеете в виду под "сессией" в контексте WebSockets.

На высоком уровне инициирование "соединения WebSocket" требует, чтобы клиент отправил HTTP-запрос GET на HTTP-сервер, тогда как запрос включает Upgrade поле заголовка Теперь, чтобы этот запрос выполнялся, клиент должен установить TCP-соединение с HTTP-сервером (это может быть очевидно, но я думаю, что здесь важно указать это явно). Последующий ответ HTTP-сервера затем отправляется через то же TCP-соединение.

Обратите внимание, что теперь, после того как ответ сервера отправлен, TCP-соединение остается открытым / активным, если оно не было активно закрыто ни клиентом, ни сервером.

Теперь, согласно RFC 6455, стандарту WebSocket, в конце раздела 4.1:

Если ответ сервера подтвержден, как указано выше, это
сказал, что Соединение WebSocket установлено и что
Соединение WebSocket находится в состоянии ОТКРЫТО

Отсюда я прочитал, что то же самое TCP-соединение, которое было инициировано клиентом перед отправкой начального HTTP-запроса GET (Upgrade), просто останется открытым и с этого момента будет служить транспортным уровнем для полнодуплексного соединения WebSocket. И это имеет смысл!

Что касается вашего вопроса, это означает, что балансировщик нагрузки будет играть роль только до того, как будет сделан первоначальный запрос HTTP GET (Upgrade), т.е. до того, как между двумя конечными точками связи будет установлено одно-единственное TCP-соединение, участвующее в создании указанного соединения WebSocket., После этого TCP-соединение остается установленным и не может быть "перенаправлено" сетевым устройством между ними.

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

Если вы ссылались на что-то еще с помощью "сеанса", то, вероятно, это сеанс, который представлен прикладным уровнем, и мы не можем комментировать этот.

Отредактируйте с учетом ваших комментариев:

так вы говорите, что балансировщик нагрузки не участвует в соединении TCP

Нет, это не так, по крайней мере, в целом. Это определенно может повлиять на установление TCP-соединения, в том смысле, что оно может решить, что делать с попыткой соединения с клиентом. Особенности зависят от точного типа балансировщика нагрузки (*, см. Ниже). Важное замечание: После того как соединение установлено между двумя конечными точками - хотя я не считаю балансировщик нагрузки конечной точкой, я обращаюсь к клиенту WebSocket и серверу WebSocket - эти две конечные точки больше не будут меняться в течение времени жизни соединения WebSocket, Балансировщик нагрузки может * все еще находиться в сетевом пути, но можно предположить, что он больше не оказывает влияния.

Следовательно, дуплексное соединение между клиентом и конечным сервером?

Да!

*** Существуют разные типы балансировки нагрузки. В зависимости от типа роль балансировщика нагрузки различается после установления соединения между двумя конечными точками. Примеры:

  • Если балансировка нагрузки происходит на основе DNS, то балансировщик нагрузки вообще не участвует в конечном TCP-соединении. Он просто сообщает клиенту, к какому хосту необходимо подключиться напрямую.
  • Если балансировщик нагрузки работает как Layer 4 ELB от AWS (документы здесь), то он, так сказать, прокси-соединения TCP. Таким образом, клиент фактически видит сам ELB как сервер. Однако происходит то, что ELB просто пересылает пакеты в обоих направлениях без изменений. Следовательно, он все еще активно участвует в соединении TCP, просто прозрачно. В этом случае фактически задействованы два постоянных TCP-соединения: одно от вас к ELB, а другое от ELB к серверу. Они снова являются постоянными в течение всего срока службы вашего соединения WebSocket.

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

Это должно быть липким. Это отличается от L7 HTTP LB, которые могут отправлять на основе HTTP-запроса.

LB может работать липко при разных подходах, т.е.

  • хэшируйте исходный IP/ порт с набором живых бэкэнд-серверов
  • после установления TCP-соединения выберите внутренний сервер и помните, что
Другие вопросы по тегам