如何在部署槽交换后优雅地迁移打开的 Websocket 连接?

How can I gracefully migrate open Websocket connections after a deployment slot swap?

在我的网络应用程序中,当用户登录应用程序时,他们的浏览器会打开一个到服务器的 Websocket,以便可以将更新推送到浏览器。

它是 Azure 应用服务中的 ASP.NET 核心 Web 应用程序(自托管)运行。我想使用 Azure 的 deployment slot swapping 功能通过零停机部署将代码更新推送到生产环境。

在我所做的有限测试中,似乎在插槽交换后 Websocket 连接保持打开状态,以连接到浏览器连接到的原始插槽。 (因此,如果浏览器的 Websocket 连接到插槽 A,并且我们交换了插槽 A 和 B,以便新连接转到插槽 B,Websocket 仍将对插槽 A 上的应用 运行 开放。)

在某些时候,旧插槽将脱机,这将强制关闭所有打开的 Websocket。我宁愿在插槽交换后尽可能优雅地重新打开 Websocket 到新插槽,这样如果我更新与 Websocket 相关的代码,所有客户端都将 运行 新代码为尽快。

这可能如何工作的草图:

  1. 插槽交换发生
  2. 已将通知发送到旧插槽上的代码 运行
  3. 旧插槽上的代码 运行 推送 Websocket 消息以重新连接
  4. 收到消息后,浏览器打开一个新的 Websocket 连接(将转到新插槽)
  5. 连接成功后,浏览器关闭旧的Websocket

有更好的方法吗?

旧插槽上的代码 运行 如何知道它何时被交换?

有没有可能优雅地处理这个问题?或者总是会有一堆竞争条件?

WebSockets 确实保持连接,因为 ARR 只能将新请求定向到 "new" 应用程序。例如,如果您在交换过程中下载一个大文件,您会看到相同的行为。

我处理这个问题的方法是让我的部署系统 (Octopus) 进行交换,然后向 "old" 应用程序发出请求,通知所有连接的 WebSocket 客户端他们需要断开并重新连接。客户端将立即断开连接,选择一个随机延迟(以防止一次重新连接数千次),然后在该延迟后重新连接。