WebSocket模块
不仅仅是IM通讯系统,在很多业务中都会有服务端需要主动推送web的场景。比如小红点提醒,新消息提醒,审批流提醒等。那么常见的推送方案有哪些?
服务端推送web方案
1.短轮询
短轮询,就是web端不停地间隔一段时间向服务端发一个 HTTP 请求,如果有新消息,就会在某次请求返回。
适用场景:
- 扫码登录:短时间内频繁查询二维码状态
- 小OA系统:客户端使用量不大的情况下可以使用
缺点:
- 大量无效请求:大量的无效请求,浪费服务器资源
- 服务端请求压力大:万人群聊频繁访问,上万并发服务扛不住。
2.长轮询
长轮询和短轮询相比,一个最大的改进之处在于:
- 短轮询模式下,服务端不管本轮有没有新消息产生,都会马上响应并返回。而长轮询模式当本次请求没有获取到新消息时,并不会马上结束返回,而是会在服务端"悬挂(hang)",等待一段时间;
- 如果在等待的这段时间内有新消息产生,就能马上响应返回。
这也意味着web端的请求超时时长得设置长一些。
优点:相比短轮询模式
- 大幅降低短轮询模式中客户端高频无用的轮询导致的网络开销和功耗开销
- 降低了服务端处理请求的 QPS
缺点:
- 无效请求:长轮询在超时时间内没有获取到消息时,会结束返回,因此仍然没有完全解决客户端"无效"请求的问题。
- 服务端压力大 :服务端悬挂(hang)住请求,只是降低了入口请求的 QPS,并没有减少对后端资源轮询的压力。假如有 1000 个请求在等待消息,可能意味着有 1000 个线程在不断轮询消息存储资源。(轮询转移到了后端)
3.Websocket长连接
长轮询
和短轮询
都算作是服务端没法主动向客户端推送的一种曲线救国
的方式,那最好的方案,就是能不能解决这个问题,因此诞生了websocket。
实现原理:客户端和服务器之间维持一个 TCP/IP 长连接,全双工通道。
基本弥补了上面的缺点,唯一的缺点就是实现起来可能会有些复杂,我们需要去管理链接。
websocket代码实现方案
支持websocket的容器很多,我们实现一般用两种常见方案。
1.tomcat实现websocket
原理和使用细节可以查看blog.csdn.net/devcloud/ar...
2.netty实现websocket
用netty实现websocket可以看项目代码,或者参考文章:blog.csdn.net/mahao25/art...
为啥我选netty不用tomcat?
- netty是nio基于事件驱动的多路复用框架,使用单线程或少量线程处理大量的并发连接。相比之下,Tomcat 是基于多线程的架构,每个连接都会分配一个线程,适用于处理相对较少的并发连接。最近的 Tomcat 版本(如 Tomcat 8、9)引入了 NIO(New I/O)模型。所以这个点并不是重点。
- Netty 提供了丰富的功能和组件,可以灵活地构建自定义的网络应用。它具有强大的编解码器和处理器,可以轻松处理复杂的协议和数据格式。Netty 的扩展性也非常好,可以根据需要添加自定义的组件。比如我们可以用netty的pipeline方便的进行前置后置的处理,可以用netty的心跳处理器来检查连接的状态。这些都是netty的优势。
websocket的连接过程
客户端依靠发起HTTP握手,告诉服务端进行WebSocket协议通讯,并告知WebSocket协议版本。服务端确认协议版本,升级为WebSocket协议。之后如果有数据需要推送,会主动推送给客户端。
连接开始时,客户端使用HTTP协议和服务端升级协议,升级完成后,后续数据交换遵循WebSocket协议。我们看看Request Headers
其中关键的字段就是Upgrade
,Connection
,告诉 Apache 、 Nginx 等服务器:注意啦,我发起的是Websocket协议,不再 使用原先的HTTP。
其中,Sec-WebSocket-Key
当成是请求id就好了。
Sec-WebSocket-Accept
: 用来告知服务器愿意发起一个websocket连接, 值根据客户端请求头的Sec-WebSocket-Key计算出来。