Skip to content

websocket 实战注意事项

shell
# 使用 websocket 的过程中发现了一个事
前后端 websocket 通信,是多个功能统一使用一个 socket 连接,通过 socket 派发的不同事件来区分功能,而不是像 http 那样,每一个功能,建立一个 http 连接
HTTP 短连接(接口)
    每请求一次功能 建立一次 TCP 连接
    请求结束 立刻断开
    不同业务:用户、订单、消息、文件,各自单独请求、单独建连
    模式:一问一答、无状态、每次都要重新请求
WebSocket / Socket.IO 长连接
    项目全局只建立 1 Socket 长连接
    连接一次,全程复用,不断开
    不同业务(聊天、通知、大屏、心跳、订单推送)
    靠「自定义事件名」区分:
        chat_msg 聊天消息
        order_change 订单状态
        system_notice 系统通知
        heart_beat 心跳检测
形象对比
    HTTP 新增一个功能 = 新加一个接口地址,新建一次请求连接
    Socket 新增一个功能 = 只新增一个事件名称,复用同一条长连接,不新建连接
代码示例
    前端代码
        const socket = io('后端地址') # 全局就 1 个 socket 实例,1 条长连接
        ## 不同功能,用不同事件区分
        socket.on('chat_msg', fn)     # 聊天功能
        socket.on('order_push', fn)   # 订单推送
        socket.on('notice', fn)       # 系统通知
    后端代码
        @SubscribeMessage('chat_msg')   # 聊天事件
        @SubscribeMessage('order_push') # 订单事件

# 还有,另外一个事儿,前后端都没用到 ws:// wss:// 相关协议
因为:WebSocket/Socket.IO 基于 HTTP 协议完成初次握手,握手成功后,自动协议升级(整个过程在浏览器上可见 ws://,业务代码无感知)
另外 WebSocket/Socket.IO 依附于后端主服务,与后端服务共用一个端口,不是独立服务;
前端填写:
    线上 HTTPS 项目:填 https://xxx
    本地开发 HTTP:填 http://xxx
握手成功后,自动协议升级:
    https 环境 自动升级为 wss:// 加密长连接
    http 环境 自动升级为 ws:// 明文长连接
全程
    不用前/后端手动写 ws:/// wss://

# 在 websocket 实战开发中一般不使用原生的 websocket API 而是使用封装好的库
前端 vue3:pnpm add socket.io-client
后端 nestjs:pnpm add socket.io

# 问题一:整个项目只能有一个 WebSocket 请求吗?
不是,可以有多个,但是 中小型项目(推荐),只建立 1 WebSocket 连接,过多路复用处理所有消息

# 问题二:什么时候需要用到多个?
如果业务之间需要隔离(如一个断了不影响另一个),可以按域名拆分:
wss://chat.example.com 聊天专用
wss://push.example.com 推送专用
wss://data.example.com 数据流专用

# 问题三:浏览器限制是多少?
Chrome、Firefox、Safari 都默认单域名最多 6 个并发 TCP 连接,Edge 可配到 256
一个页面内,所有 XHR、fetch、图片、WebSocket 加起来,往同一个域名最多同时开 6 TCP 连接。
注意:TCP 连接数不是 http 请求数,TCP 连接相当于高速通道,而 http 请求相当于过往车辆,如果车辆过多就要排队了

# 问题四:服务器能撑多少? 
调优后可到 50 万+ 空闲连接,
    # 方案:nginx 负载均衡横向扩展,同时启动多个后台服务实例,一台代理一万
    负载均衡 + Sticky Session(ip_hash策略)
    操作系统调优 - 支撑单机5万+连接
    如果用Node.js实现,建议将目标设定为一个服务器处理5-10万连接,然后横向扩展。一个服务器 16核CPU + 32GB运行内存,
    负载均衡方案,不是都用 nginx
        第一层:nginx 做负载均衡代理到 10 台服务器上 
        第二层:每台服务器上的Nginx再做负载均衡,把流量分发给本机的 5 个NestJS进程。 每个进程承担 10000 20000 的并发数


# 问题五:最大瓶颈是什么? 
连接抖动(频繁握手)> 内存 > CPU > 带宽