webSocket推送
推模式:服务端推送消息到浏览器
拉模式与推模式的区别
拉模式:前端轮询的调用接口
aaa
整体架构!
网关集群!
单机瓶颈
维护海量长连接会花费不少内存
消息推送瞬时消耗大量 CPU 资源
消息推送瞬时帯宽高达 400~600MB (4-6 Gbits),是主要瓶颈!
单机架构!
内核瓶颈 - 优化原理
减少网络小包的发送
内核瓶颈 - 优化方案
将同一秒内的 N 条消息,合并成 1 条消息
合并后,每秒推送次数只等于在线连接数
锁瓶颈 - 优化原理
大拆小
锁瓶颈 - 优化方案
连接打散到多个集合中,每个集合有自己的锁
多线程并发推送多个集合,避免锁竞争
读写锁取代互斥锁,多个推送任务可以并发遍历相同集合
CPU 瓶颈 - 优化原理
减少重复计算
CPU 瓶颈 - 优化方案
json 编码前置,1 次消息编码 + 100 万次推送
消息合并前置,N 条消息合并后只编码 1 次
CPU 瓶颈
浏览器与服务端通常采取 json 格式通讯
json 编码非常耗费 CPU 资源
向 100 万在线推送 1 次,则需 100 万次 json encode
锁瓶颈
需要维护在线用户集合(100 万在线),通常是一个字典结构
推送消息即遍历整个集合,顺序发送消息,耗时极长
推送期间,客户端仍旧正常上/下线,所以集合需要上锁
內核瓶颈
推送量大:100万在线 * 10条/秒 = 1000万条/秒
内核瓶颈:linux 内核发送 TCP 的极限包频 ~ 100 万/秒
3 个性能瓶颈
內核瓶颈
锁瓶颈
CPU 瓶颈
內部原理
启动读协程,循环读取 WebSocket,将消息投递到 in channel
启动写协程,循环读取 out channel,将消息写给 WebSocket
API 原理
SendMessage 将消息投递到 out channel
ReadMessage 从 in channel 读取消息
隐藏细节,封装 API
封装 connection 结构,隐藏 ebsocket/底层连接
封装 connection 的 API,提供 Send/Read/Close 等线程安全接口
缺乏工程化的设计
其他代码模块,无法直接操作 Websocket 连接
Websocket 连接非线程安全,并发读/写需要同步手段
Websocket 是 HTTP 协议 Upgrade 而来
使用 http 标准库快速实现空接口:/ws
NodeJS:单线程模型,推送性能有限
C/C++:TCP 通讯、Websocket 协议实现成本高
Go!
多线程,基于协程模型并发
成熟的 WebSocket 标准库,无需造轮子
Heartbeat
Upgrade: websocket
抓包观察
使用 chrome 开发者工具,观察 WebSocket 通讯流程
传输原理
协议升级后,继续复用 HTTP 的底层 socket 完成后续通讯
message 底层被切分成多个 frame 帧传输
编程时只需操作 message,无需关心 frame
框架底层完成 TCP 网络 I/O,WebSocket 协议解析,开发者无需关心
通讯流程!
基于 WebSocket 推送
浏览器支持的 socket 编程,轻松持服务端的长连接
基于 TCP 可靠传输之上的协议,无需开发者关心通讯细节
提供了高度抽象的编程接口,业务开发成本较低
推模式
仅在数据更新时才需要推送
需要维大量的在线长连接
数据更新后可以立即推送
拉模式
数据更新频率低,则大多数请求是无效的
在线用户数量多,则服务端的查询负载很高
定时轮询拉取,无法满足时效性要求
N 个直播间
推送频率:N*10 亿条/秒
1 个直播
在线人数:100 万
发送弹幕:1000 条/秒
推送频率:100 万*1000 条/秒 = 10 亿条/秒
课程章节
单幕系统的技术挑战
掌握 Websocket 协议
GO 实现 WebSocket 服务端
干万级弹幕系统的架构秘密
课程回顾与总结