知识卡片
360消息系统的六大组件架构
内容
360消息系统(长连接push系统,实时在线数亿量级)由六个职责清晰分离的组件构成。Dispatcher Service根据客户端请求信息,把符合网络和区域条件的一组长连接服务器IP传给客户端,客户端拿到IP后建立长连接、连上Room Service。Room Service是长连接网关,负责hold住用户连接、把用户注册进Register Service,本身还承担接入安全策略、白名单、IP限制等把关工作。Register Service是全局session存储组件,存储和索引用户的相关信息供查询获取。Coordinator Service负责转发用户的上行数据(包括接入方订阅的用户状态回调),并协调各组件间需要异步完成的操作(比如踢用户下线这类需要从Register拿出其他用户信息再做异步处理的场景)。Saver Service是存储访问层,承担对Redis和MySQL的读写,同时提供部分业务逻辑相关的内存缓存(比如广播信息可以在这里缓存);Saver还承担一条重要的防御性策略——因为客户端SDK可能被恶意或意外修改、导致加载了消息却不回复ACK,如果不做处理服务端就不会删除消息,消息会被反复加载形成死循环,Saver在这里做判断和拦截,体现了”客户端永远不可信”这条设计原则。Center Service是提供给接入方的内部API服务器,负责单播/广播接口、状态查询接口,以及运维管理相关的API。用两个例子理解组件如何协作:发一条单播消息时,Center先向Register查询这个用户之前注册的连接通道标识和Room实例地址,再通过对应的Room Service把消息下发给长连接;而全网广播这种更重的工作,需要先把整个任务拆解成一系列子任务分发给所有Center,每个子任务再分别拿到在线和离线的所有用户、批量推给Room Service,这个过程会让整个集群在那一瞬间承受很大压力。此外还有Deployd/Agent Service负责部署管理各进程、收集组件状态信息,以及ZooKeeper和团队自研的Keeper负责整个系统的配置文件管理和简单调度。
结构图:
flowchart LR
A["客户端"] -->|"请求接入IP"| B["Dispatcher Service\n返回符合网络/区域的Room IP组"]
A -->|"建立长连接"| C["Room Service\n长连接网关,接入安全策略"]
C -->|"注册用户"| D["Register Service\n全局session存储"]
E["Center Service\n对接入方的API"] -->|"查询用户连接位置"| D
E -->|"下发消息"| C
F["Coordinator Service\n转发上行数据+异步协调"] --- D
G["Saver Service\n存储访问层\nRedis/MySQL读写"] --- E
G -.->|"客户端不可信\n防止消息反复加载死循环"| G