☰
网关架构:知乎千万级长连接网关架构
2026/10/20 11:09:02 网站建设 项目流程

知乎千万级长连接网关架构

知乎长连接网关要服务的不是单一业务,而是多个 App 和十几个形态各异的长连接业务。因此它的核心目标不是“为某个业务做一套专用长连接”,而是做一套共享、可水平扩展、业务解耦的通用长连接系统。

一、发布订阅模型

多客户端、多业务后端之间如果直接耦合,协议升级和业务变更会互相影响。知乎采用发布订阅模型:

  • 客户端和业务后端只约定 Topic;
  • 网关不关心业务协议和序列化方式;
  • 消息以二进制数据传递。

订阅 topic

订阅 topic

发布消息

发布消息

客户端 1

长连接 Broker

客户端 2

业务后端 1

Kafka

业务后端 2

二、权限控制

发布订阅模型解耦了业务协议,但还需要控制客户端对 Topic 的访问权限。网关无法知道某个 Live 是否已付费,这类业务状态只有业务后端知道。因此 ACL 支持回调鉴权:

  • 配置 Topic 的订阅/发布动作通过 HTTP 回调给业务后端;
  • 业务后端返回是否允许。

对于只需要当前用户私有 Topic 的场景,则通过 Topic 模板变量降低接入成本。例如 Topic 中包含用户名变量,网关可以独立判断是否允许用户订阅自己的 Topic。

三、消息可靠性

TCP 保证传输顺序,但不能解决客户端 Crash、业务异常、连接中断造成的数据丢失。知乎实现了回执和重传:

客户端Broker业务后端客户端Broker业务后端alt[未收到 ACK]下发消息推送消息并暂存未确认队列ACK删除未确认消息重新发送

四、系统架构

设计优先考虑可靠性、水平扩展、依赖组件成熟度和简单性。系统拆成四个组件:

组件技术职责
接入层OpenResty负载均衡、会话保持
Broker容器化服务协议解析、认证鉴权、发布订阅
会话存储Redis持久化会话和未确认消息
消息枢纽Kafka业务后端与 Broker 之间解耦和削峰

客户端

OpenResty 接入层

Broker 1

Broker 2

Redis

Kafka

业务后端

接入层使用 Nginx preread 机制,读取客户端第一个报文中的客户端标识,再做一致性 Hash,保证同一个客户端稳定路由到同一个 Broker。这比按来源 IP Hash 更均匀,也能在网络切换后保持会话。

五、海量数据发布

Broker 根据路由配置发布到 Kafka Topic,同时根据订阅配置消费 Kafka 下发消息。路由规则和订阅规则分离后,可以组合出四种场景:

  1. 只发布不消费:数据上报;
  2. 发布后也消费:普通即时通讯;
  3. 只消费不下发:纯推送;
  4. 路由到一个 Topic,从另一个 Topic 消费:过滤或预处理。

这种组合足够覆盖绝大多数消息流转场景。

六、会话与 QoS

重要 Topic 消息会被标记 QoS 1。Broker 将消息写入 Redis 未确认队列后下发,收到客户端 ACK 再删除。这样单个 Broker 宕机后,客户端重连到其他 Broker 也能恢复 Session 数据。

订阅关系如果使用单个全局 HashMap 加锁,锁冲突会非常严重。知乎通过分片 HashMap 降低锁粒度:创建数百个 HashMap,按 Key Hash 取模后再操作,把全局锁分散到多把锁。

下发侧参考 TCP 滑动窗口设计并行发送机制:

滑动窗口

消息 1

消息 2

消息 3

等待 ACK

等待 ACK

等待 ACK

正常场景下基于 TCP 的顺序性,无需逐条重试;只有重连后才对窗口内未确认消息重发,客户端保留窗口大小缓冲区去重。

七、总结

知乎长连接网关把协议设计、权限控制、可靠传输、水平扩展和会话持久化拆开处理。发布订阅解决业务解耦,Kafka 解决内部消息枢纽和削峰,Redis 解决会话持久化,分片锁和滑动窗口解决性能与吞吐。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询