微服务架构与每个浏览器都有一个 Websocket 连接

USS*_*ana 6 architecture websocket microservices

遵循典型的微服务 REST 架构,其中多个服务器运行并公开不同的控制器,为每个功能单独提供服务。

我的问题是这样的:

假设我的业务逻辑 = 一个实时 Web 应用程序,需要实时计算和实时响应,其中应用程序中的多个客户端相互通信。

我的选择仅限于仅在每个浏览器之间使用 websocket 连接,并在它们之间连接中介服务器。

但是,该架构对我来说有点模糊,因为我对整体中介不感兴趣!

如果我遵循 REST 微服务架构,我将强制每个浏览器打开多个/大量套接字连接,这不是我的目标

我的方法是通过来自每个客户端的一个套接字连接消耗所有套接字事件,并在后端领域处理它

我的想象力让我进一步想象一个包含多个微服务的架构,如下所示:

  1. 套接字处理程序服务
  2. 特色1服务
  3. 特色2服务

全部与内部插座连接,就像一个大后端网格一样

但这会失败,因为我需要扩展...扩展每个功能后端服务器以支持每秒数百万个请求。

那么这会让我维护彼此相关的每个集群?

通过阅读本文,您可能会理解这个主题的原因需要一些架构思想。

我对高可维护性和性能的追求需要一个复杂的架构,但我越想它,我就越会回到单体方法。

有推荐的架构吗?

Jan*_*ert 4

不确定推荐的架构,但我会给出我的想法,因为我一直在与类似的架构决策作斗争。

在前端,假设您正在处理 30 万个用户,假设单个服务器可以处理 5k 套接字连接,那么负载均衡器后面将有 60 台服务器。这 60 台服务器中的每台服务器大约都会打开 5k 个套接字连接,如果用户刷新浏览器,他将获得与 60 台服务器中任何一台服务器的新套接字连接。

这60台服务器每台都连接到一个Kafka集群

连接到这 60 台服务器中的任何一台后,您将返回某种标识令牌、GUID 或其他内容 ( 309245f8-05bd-4221-864f-1a0c42b82133 ),然后该服务器将通过 Kafka 向 GUID 连接到其自身的所有其他 59 台服务器309245f8-05bd-4221-864f-1a0c42b82133以及这 59 台服务器中的每台进行广播将更新其内部注册表以记录309245f8-05bd-4221-864f-1a0c42b82133属于 Server1 的信息。

您需要决定当用户刷新时会发生什么,他会丢失现有消息还是您想要保留这些消息?如果用户在刷新后继续接收消息,即使用户现在连接到新服务器,浏览器需要将该 GUID 存储在 Cookie 或其他内容中,在连接到新服务器时,该新服务器将向所有其他 59现在属于 Server2 和 Server1 的服务器309245f8-05bd-4221-864f-1a0c42b82133将更新自身以记录它。

将 GUID 存储在前端,需要考虑安全性,如果有人劫持该 GUID,他们可以拦截您的请求,因此请务必将 Cookies 设置为 HTTP Only、Secure 并设置相关的 CORS 设置。

你的后端将是监听来自 Kafka 消息的服务器,你可以通过这种方式拥有任意数量的服务,如果一台服务器难以跟上,只需启动更多实例,从 1 个实例到 2 个实例,你的处理能力就会加倍(举个例子)。这些后端实例中的每一个都将跟踪前端具有的相同注册表,只是后端将跟踪哪个前端实例处理哪个 GUID,而不是跟踪哪个套接字通过 GUID 连接到哪个前端实例。

通过套接字接收到消息后,Server2 将通过 Kafka 发布消息,任意数量的后端实例都可以获取该消息并进行处理。该消息中包含 GUID,因此如果需要返回响应,后端将简单地发回一条标有该 GUID 的消息,正确的前端服务器将拾取该消息并通过套接字将响应消息发送回浏览器客户。

如果 60 个前端实例中的任何一个实例离线,则 websocket 应重新连接到任何剩余实例,并应通知后端这些 5k GUID 已移至其他服务器。如果消息到达错误的服务器,前端实例应将该消息发送回后端并重新路由指令。

Kafka 只是众多可能的解决方案之一,您可以使用 RabbitMQ 或任何其他队列系统或自己构建一个。消息传递队列应该具有高可用性,并根据需要自动缩放,并且决不应该丢失消息。

简而言之,负载均衡器后面的许多前端实例使用消息队列在它们之间进行同步,并与有权访问数据库和集成的后端实例进行通信。