Slack 最近公布了它如何每天在全球范围内发送数百万条实时消息。该公司提供了对其Pub/Sub 架构的全面洞察,旨在大规模管理实时消息。它强调了跨不同时区和地区传递实时消息所带来的独特挑战,以及 Slack 的工程师如何设计基础架构来处理这些挑战。
Slack 的高级软件工程师Sameera Thangudu解释了这种架构的重要性:
我们的服务器为每个主机提供数千万个频道,数千万个连接的客户端,我们的系统在 500 毫秒内将消息传递到世界各地。凭借我们当前架构的线性可扩展性,我们的预测表明我们可以为更多的客户提供服务。
她表示,该公司计划增强其架构,以服务更重要的客户群。
该系统的后端由几个服务组成。频道服务器 (CS) 是有状态的内存服务器,用于保存频道历史记录。一致的哈希机制将每个 CS 映射到通道子集。在高峰时期,每个主机服务约 1600 万个频道。Consistent hash ring manager (CHARMs) 为 CS 管理一致性哈希环,确保在 20 秒内更换不健康的 CS。Consul 存储一致性哈希的最新配置。
网关服务器 (GS) 与 CS 一样,是有状态的内存服务器。他们维护用户信息和 WebSocket 频道订阅,并充当 Slack 客户端和 CS 之间的接口。GS 部署在多个地理区域以优化连接速度。管理服务器 (AS) 是无状态的内存服务器,连接 Webapp 后端和 CS。最后,存在服务器 (PS) 跟踪在线用户,为 Slack 客户端中的绿色存在点提供动力。
每个 Slack 客户端都有一个到 Slack 服务器的持久 WebSocket 连接,以接收实时事件以维护其状态。客户端通过几个步骤建立 WebSocket 连接,例如从 Webapp 后端获取用户令牌和 WebSocket 连接设置信息。然后客户端向最近的边缘区域发起 WebSocket 连接,GS 获取用户信息并向客户端发送第一条消息。Envoy负载平衡传入流量并处理 TLS 终止。
客户端设置完成后,通道中发送的每条消息都会广播到通道中在线的所有客户端。消息通过 Webapp API、AS 和 CS,然后发送到全球每个订阅的 GS。收到消息的每个 GS 将其发送给订阅该频道 ID 的每个连接的客户端。
除了聊天消息之外,事件是另一种实时更改客户端状态的消息类型。瞬态事件(例如用户在频道中键入内容)遵循略有不同的流程,因为数据库不会保留这些事件。下图说明了此流程。