当前位置: 首页 > 面试题库 >

在没有粘性会话的情况下使用TCP负载平衡器代理W​​ebSocket

包子航
2023-03-14
问题内容

我想使用Amazon Elastic Load Balancer将WebSocket连接代理到多个node.js服务器。由于Amazon
ELB不提供实际的WebSocket支持,因此我需要使用其原始的TCP消息传递。但是,我试图了解没有某种粘性会话功能的情况如何工作。

我了解WebSocket的工作方式是首先从客户端发送HTTP升级请求,服务器通过发送正确处理密钥身份验证的响应来处理该请求。服务器发送该响应并获得客户端批准后,该客户端与服务器之间便建立了双向连接。

但是,假设客户端在批准服务器响应后将数据发送到服务器。如果将数据发送到负载平衡器,然后负载平衡器将该数据中继到未处理原始WebSocket升级请求的其他服务器,那么该新服务器将如何知道WebSocket连接?还是客户端会自动绕过负载平衡器并将数据直接发送到处理初始升级的服务器?


问题答案:

我认为,为了回答这个问题,我们需要理解的是在整个WebSocket创建过程中基础TCP连接如何精确地演变。您将认识到WebSocket连接的 粘性
部分是基础TCP连接本身。我不确定在WebSockets上下文中“会话”的含义。

在较高级别上,启动“ WebSocket连接”要求客户端向HTTP服务器发送HTTP
GET请求,而该请求包括Upgrade标头字段。现在,为了实现此请求,客户端需要建立与HTTP服务器的TCP连接(这可能很明显,但是我认为在此处明确指出这一点很重要)。然后,通过
相同的 TCP连接发送后续的HTTP服务器响应。

请注意,现在,在发送服务器响应之后,如果客户端或服务器未主动关闭TCP连接,则该TCP连接仍然处于打开/活动状态。

现在,根据RFC
6455,WebSocket标准,在第4.1节的末尾:

如果服务器的响应如上所述得到验证,则
表示 已建立
WebSocket连接,并且WebSocket连接处于OPEN状态

我从这里了解到,客户端在发送初始HTTP
GET(升级)请求之前发起的同一TCP连接将保持打开状态,从现在开始将用作全双工WebSocket连接的传输层。这很有道理!

关于您的问题,这意味着负载平衡器将仅在发出初始HTTP GET(升级)请求 之前 ,即
两个通信端点之间建立涉及该WebSocket连接创建的一个和唯一的TCP连接 之前
,扮演角色。。此后,TCP连接将保持建立状态,并且不能通过两者之间的网络设备“重定向”。 __

我们可以得出这样的结论:在您的会话术语中 ,TCP连接定义了会话 。只要WebSocket连接处于活动状态(即未终止),就 可以定义
并提供并驻留在其自己的会话中。没有什么可以改变这个会议。在这张图中,两个独立的WebSocket连接不能共享同一会话。

如果您用“会话”引用其他内容,则可能是应用程序层引入的会话,我们无法对此进行评论。

根据您的评论进行编辑:

所以您说的是负载平衡器不参与TCP连接

不,至少在总体上是不正确的。从某种意义上说,它可以决定如何处理客户端连接尝试,它绝对会影响TCP连接的建立。具体细节取决于负载均衡器的确切类型(,请参见下文)。重要提示:在两个端点之间建立连接后-
虽然我不认为负载均衡器是一个端点,但我指的是WebSocket客户端和WebSocket服务器-
两个端点在WebSocket连接的生命周期中将不再更改。负载均衡器可能
仍在网络路径中,但可以假定不再具有影响力。

因此,全双工连接是在客户端和最终服务器之间吗?

是!

***有不同类型的负载平衡。根据类型,在两个端点之间建立连接后,负载均衡器的作用会有所不同。例子:

  • 如果负载平衡是基于DNS发生的,则负载平衡器完全不参与最终的TCP连接。它只是告诉客户端哪个主机必须 直接 连接。
  • 如果负载均衡器的工作方式类似于AWS的第4层ELB(此处提供文档),则可以说它代理了TCP连接。因此,客户端实际上会将ELB本身视为服务器。但是,发生的情况是,ELB只是沿两个方向转发包裹,而没有进行任何更改。因此,它仍然透明地大量参与TCP连接。在这种情况下,实际上涉及两个永久TCP连接:一个从您到ELB,一个从ELB到服务器。这些在WebSocket连接的整个生命周期中都是永久的。


 类似资料:
  • 在我的AWS帐户中,我当前有一个网络负载平衡器(TCP),它指向两个可用性区域(web服务器)上的两个Ec2实例,每个可用性区域都运行一个tomcat,它指向一个Ec2实例,即应用程序服务器/数据库。 在NLB上,粘性会话是启用的,因此当我在单个选项卡上从Chrome访问网络服务器时,一切正常,我的所有用户流量都发送到单个网络服务器。当我打开一个新选项卡时,似乎启动了一个新会话,我的用户流量可以发

  • 我想使用Feign客户机,并按服务名称在中提供URL。 我使用Spring Boot,并且依赖于Spring Cloud: 我知道如何对属性进行硬编码以从属性读取URL: : 这是一个更好的,但我想脱钩的财产名称与虚假客户端。我只想使用。 这个解决方案似乎更好,因为代码中的Feign客户机只包含(没有URL或URL的耦合属性名称)。这正是我想要的。 但在日志中,我看到Spring/Ribbon为我

  • 我需要一些nginx负载平衡方面的帮助。我有一个docker实例,它服务于一个静态网页,它有两个容器,比如说192.168。1.1:8081 - 当我输入这些IP地址192.168.1.1时,这些IP必须服务于我的两个站点之间的负载。 在我的Nginx中,我必须为此设置两个文件 Nginx。conf,在这些文件中,我必须包含我的默认值。conf文件。违约conf文件包含以下信息。 当我键入192.

  • 我正在使用编写负载均衡器。 负载平衡器侦听本地传输地址。就Netty而言,只创建了一个频道来监听该地址。然后,(单线程事件循环组的)单线程将传入的UDP数据包调度到工作线程池进行处理(这里,处理意味着执行负载平衡)。 在出站端,可以使用多个服务器。对于每个接收到的UDP数据包,关联的工作线程选择一个服务器,并将UDP数据包转发到此服务器。为了转发UDP数据包,需要一个通道。 我可以看到四种方法:

  • 我试图使用Kubernetes来明确定义配置和部署,我也喜欢Kubernetes的pod调度机制。目前,只有2个应用程序在3个节点上的2个副本上运行。但是谷歌的Kubernetes引擎的负载平衡器对于像我们这样的小应用程序来说非常昂贵(至少目前如此),同时我不愿意改为在容器上托管单个实例的解决方案,也不愿意在Docker swarm等上部署应用程序。 使用节点的IP似乎是一种黑客行为,我认为这可能

  • 因此,在单个节点上运行和扩展运行多个 Pod 的部署效果很好,并且当使用类型“nodePort”公开服务时,可以很好地平衡对该单个节点上多个 Pod 之间的虚拟 IP 的请求。 此后,我向我的集群添加了一个额外的节点,当使用nodePort公开服务,然后在2个节点上运行pods时,我当然需要具体指定每个主机,以访问在不同节点上的不同pods中运行的endpoint。 我想将请求发送到单个VIP,并