- 无效请求多
- 查询负载高
- 定时轮训,时效性差
- 数据更新时推送
- 维护大量在线长连接
- 可以立即推送
- 浏览器支持的socket编程,轻松维持服务端长连接
- 基于TCP之上
client --- upgrade --> server
client <-- switching --- server
client --- message --> server
client <-- message --- server- 复用HTTP的底层socket完成后续通讯
- message底层被切分成多个frame帧传输
- 编程只需要关心message,不需要关心frame
- 框架底层完成TCP IO,WebSocket协议解析
- 使用websocket.Upgrader 完成握手协议,得到ws长连接
- 操作ws api,读取client msg
- ws非线程安全,需要自己完善并发读写
- 内核瓶颈
- 锁瓶颈
- CPU瓶颈
- 推送量大: 100w在线 * 10条/s = 1000w条/s
- 内核瓶颈: linux内核发送tcp的极限包频: 100w/s
- 需要维护在线用户集合(100w在线),e.g. hash,dict存储所有连接
- 推送消息:遍历整个集合,顺序发送消息,耗时长
- 推送期间,client仍旧上下线,所以集合需要上锁
- browser & server 采用json交互
- json编码耗费cpu资源
- 100w在线推送1次,需要做100w次json decode
- 减少网络小包发送(消息合并):将同一秒内的N条消息,合并1条,每秒推送次数 只等于在线连接数
- 锁拆小:将连接打散到多个集合中,每个集合有自己的锁
- 多线程并发推送多个集合,集合互相之间不会锁,避免锁竞争
- 读写锁取代互斥锁,多个推送任务可以并发遍历相同集合
- 减少重复计算:json编码前置,1次消息编码 + 100w次推送
- 消息合并前置,N条消息合并后只需要编码1次
长链接1 -- 长链接2 -- 长链接3
集合0 -- 集合1 -- 集合2
分发 -- 分发 -- 分发
消息打包 + 编码
消息1 -- 消息2 -- 消息3
- 维护长链接:内存
- 消息推送瞬时:吃CPU
- 消息推送瞬时带宽 400~600MB,是主要瓶颈
Q:不知道哪个直播间在哪个网关节点 A:全广播 or 逻辑集群
连接1 -- 连接2 -- 连接3
--------- LB ---------
网关1 -- 网关2 -- 网关3
logic -- logic <-- 业务方
- 基于HTTP2协议 向 gateway集群分发消息
- HTTP2 支持连接复用,用作RPC性能好
- 基于HTTP1 对外提供推送API
- 对业务友好