Azure 上的 SignalR 连接与负载均衡器
SignalR connections on Azure with load balancer
我在 Azure 资源管理器中进行了下一个设置:
- 1 个规模集,其中 2 个虚拟机具有 Windows Server 2012。
- 1 个 Azure Redis 缓存(C1 标准)
- 1 个 Azure 负载均衡器(OSI 网络参考堆栈中的第 4 层)
负载均衡器基本上使用 :
配置
https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-get-started-internet-portal
.规则的会话持久性设置为 none。
在规模集中的两个 VM 上,我都部署了一个测试 Web 应用程序,它在 .Net 4.5.2 上使用 SignalR 2。
测试 Web 应用使用 Azure Redis 缓存作为背板。
Web 应用程序项目可以在 github 上找到:https://github.com/gaclaudiu/SignalrChat-master.
在测试过程中,我确实注意到在打开 Signalr 连接后,从客户端发送的所有数据,在接下来的请求中,都从规模集中到达同一台服务器,在我看来 SignalR 连接知道从规模集到哪个服务器。
我很想知道更多关于它是如何工作的,我试图在互联网上做一些研究,但在这一点上找不到明确的东西。
我也很想知道下一个案例会发生什么:
客户端 1 有一个 Signalr 打开连接到服务器 A。
来自客户端 1 的下一个请求通过 SignalR 转到服务器 B。
这会导致错误吗?
或者客户端只会收到没有打开连接的通知,它会尝试打开一个新连接?
好吧,我很惊讶它能正常工作。问题是:signalr 执行多个请求,直到连接建立并且 运行。无法保证所有请求都发送到同一个 VM。特别是如果没有启用会话持久性。我有一个类似的问题。您可以在负载均衡器中激活会话持久性,但正如您指出的那样,在 OSI 第 4 层上执行操作将使用客户端 ip 执行此操作(想象一下来自同一办公室的所有人都使用相同的 IP 访问您的API)。在我们的项目中,我们使用与 cookie 亲和力一起工作的 Azure 应用程序网关 -> OSI 应用程序层。到目前为止,它似乎按预期工作。
SignalR 只知道您在启动连接时提供的 url,并使用它向服务器发送请求。我相信 Azure App Service 默认使用粘性会话。您可以在此处找到有关此内容的一些详细信息:https://azure.microsoft.com/en-us/blog/azure-load-balancer-new-distribution-mode/
当使用多个服务器和 scale-out 时,客户端可以向任何服务器发送消息。
在您的 Azure 负载均衡器上,您需要配置会话持久性。这将确保当客户端请求定向到服务器 A 时,来自该客户端的任何后续请求都将转到服务器 A。
Session persistence specifies that traffic from a client should be handled by the same virtual machine in the backend pool for the duration of a session. "None" specifies that successive requests from the same client may be handled by any virtual machine. "Client IP" specifies that successive requests from the same client IP address will be handled by the same virtual machine. "Client IP and protocol" specifies that successive requests from the same client IP address and protocol combination will be handled by the same virtual machine.
谢谢大家的回答。
做了一些阅读,似乎 azure 负载均衡器默认使用 5-touple 分布。
这是文章 https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-distribution-mode
5-touple 的问题是每个传输会话都是粘性的。
我认为这导致客户端请求使用 signalr 命中规模集中的相同 Vm。我认为平衡器将信号器连接解释为单个传输会话。
应用程序网关从一开始就不是一个选项,因为它有很多我们不需要的功能(所以为我们不使用的东西付费是没有意义的)。
但现在看来,应用程序网关是 azure 中唯一能够在平衡流量时进行循环的平衡器。
我认为您误解了负载均衡器的工作原理。每个 TCP 连接都必须将其所有数据包发送到相同的目标 VM 和端口。如果在发送多个数据包后,TCP 连接突然将其余数据包发送到另一个 VM and/or 端口,则 TCP 连接将无法工作。因此,负载均衡器会在建立 TCP 连接时对 TCP 连接的目的地做出一次且仅一次的决定。建立 TCP 连接后,其所有数据包都会在连接期间发送到同一目的地 IP/port。我认为您假设来自同一 TCP 连接的不同数据包可以在不同的 VM 上结束,但事实并非如此。
因此,当您的客户端创建 WebSocket 连接时,会发生以下情况。负载均衡器接收传入的 TCP 连接请求。它根据分发模式决定将请求发送到哪个目标 VM。它在内部记录此信息。该 TCP 连接的任何后续传入数据包都会自动发送到同一 VM,因为它从该内部 table 查找适当的 VM。因此,您的 WebSocket 上的所有客户端消息都将在相同的 VM 和端口上结束。
如果您创建一个新的 WebSocket,它可能会在不同的 VM 上结束,但来自客户端的所有消息都将在同一个不同的 VM 上结束。
希望对您有所帮助。
我在 Azure 资源管理器中进行了下一个设置:
- 1 个规模集,其中 2 个虚拟机具有 Windows Server 2012。
- 1 个 Azure Redis 缓存(C1 标准)
- 1 个 Azure 负载均衡器(OSI 网络参考堆栈中的第 4 层)
负载均衡器基本上使用 :
配置 https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-get-started-internet-portal .规则的会话持久性设置为 none。
在规模集中的两个 VM 上,我都部署了一个测试 Web 应用程序,它在 .Net 4.5.2 上使用 SignalR 2。 测试 Web 应用使用 Azure Redis 缓存作为背板。 Web 应用程序项目可以在 github 上找到:https://github.com/gaclaudiu/SignalrChat-master.
在测试过程中,我确实注意到在打开 Signalr 连接后,从客户端发送的所有数据,在接下来的请求中,都从规模集中到达同一台服务器,在我看来 SignalR 连接知道从规模集到哪个服务器。
我很想知道更多关于它是如何工作的,我试图在互联网上做一些研究,但在这一点上找不到明确的东西。
我也很想知道下一个案例会发生什么: 客户端 1 有一个 Signalr 打开连接到服务器 A。 来自客户端 1 的下一个请求通过 SignalR 转到服务器 B。
这会导致错误吗? 或者客户端只会收到没有打开连接的通知,它会尝试打开一个新连接?
好吧,我很惊讶它能正常工作。问题是:signalr 执行多个请求,直到连接建立并且 运行。无法保证所有请求都发送到同一个 VM。特别是如果没有启用会话持久性。我有一个类似的问题。您可以在负载均衡器中激活会话持久性,但正如您指出的那样,在 OSI 第 4 层上执行操作将使用客户端 ip 执行此操作(想象一下来自同一办公室的所有人都使用相同的 IP 访问您的API)。在我们的项目中,我们使用与 cookie 亲和力一起工作的 Azure 应用程序网关 -> OSI 应用程序层。到目前为止,它似乎按预期工作。
SignalR 只知道您在启动连接时提供的 url,并使用它向服务器发送请求。我相信 Azure App Service 默认使用粘性会话。您可以在此处找到有关此内容的一些详细信息:https://azure.microsoft.com/en-us/blog/azure-load-balancer-new-distribution-mode/ 当使用多个服务器和 scale-out 时,客户端可以向任何服务器发送消息。
在您的 Azure 负载均衡器上,您需要配置会话持久性。这将确保当客户端请求定向到服务器 A 时,来自该客户端的任何后续请求都将转到服务器 A。
Session persistence specifies that traffic from a client should be handled by the same virtual machine in the backend pool for the duration of a session. "None" specifies that successive requests from the same client may be handled by any virtual machine. "Client IP" specifies that successive requests from the same client IP address will be handled by the same virtual machine. "Client IP and protocol" specifies that successive requests from the same client IP address and protocol combination will be handled by the same virtual machine.
谢谢大家的回答。 做了一些阅读,似乎 azure 负载均衡器默认使用 5-touple 分布。 这是文章 https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-distribution-mode 5-touple 的问题是每个传输会话都是粘性的。 我认为这导致客户端请求使用 signalr 命中规模集中的相同 Vm。我认为平衡器将信号器连接解释为单个传输会话。
应用程序网关从一开始就不是一个选项,因为它有很多我们不需要的功能(所以为我们不使用的东西付费是没有意义的)。
但现在看来,应用程序网关是 azure 中唯一能够在平衡流量时进行循环的平衡器。
我认为您误解了负载均衡器的工作原理。每个 TCP 连接都必须将其所有数据包发送到相同的目标 VM 和端口。如果在发送多个数据包后,TCP 连接突然将其余数据包发送到另一个 VM and/or 端口,则 TCP 连接将无法工作。因此,负载均衡器会在建立 TCP 连接时对 TCP 连接的目的地做出一次且仅一次的决定。建立 TCP 连接后,其所有数据包都会在连接期间发送到同一目的地 IP/port。我认为您假设来自同一 TCP 连接的不同数据包可以在不同的 VM 上结束,但事实并非如此。
因此,当您的客户端创建 WebSocket 连接时,会发生以下情况。负载均衡器接收传入的 TCP 连接请求。它根据分发模式决定将请求发送到哪个目标 VM。它在内部记录此信息。该 TCP 连接的任何后续传入数据包都会自动发送到同一 VM,因为它从该内部 table 查找适当的 VM。因此,您的 WebSocket 上的所有客户端消息都将在相同的 VM 和端口上结束。
如果您创建一个新的 WebSocket,它可能会在不同的 VM 上结束,但来自客户端的所有消息都将在同一个不同的 VM 上结束。
希望对您有所帮助。