【解决方案】服务器推送

在服务器消息推送场景中,解决方案无外乎浏览器定时询问服务器是否有新数据,另外一种则是服务器在有新数据的时候主动推送给浏览器。大概有如下几种方案:

Server Push Solution

1. 短轮询

Ajax短轮询是较常见和简单的方式。前端定时向服务端发送请求获取数据。

优点:

  • 实现简单

缺点:

  • 有延迟,延迟度与发送请求的间隔正相关
  • 频繁建立和关闭HTTP连接,服务器压力较大

2. 长轮询

前端任然通过Ajax定时发送请求获取数据,但是服务器收到请求之后如果没有最新数据,则将请求保持住,直到有数据才响应前端。

Long Polling

优点:

  • 相对短链接,发起请求的频率更加合理

缺点:

  • 服务器需要保持连接,占用资源(可以通过异步方式进行处理,释放连接线程资源。实现:Servlet3异步任务/Spring DeferedResult)
  • 服务器需要对应的逻辑支持

3. SSE(Server-Send-Events)

H5提出的长连接服务器推模型。客户端与服务端建立连接指定Content-Type:text/event-stream,告诉服务器以流的方式响应数据,做到一次请求,多次响应。

在这种模式中,服务端响应的数据格式是固定的:

操作码:数据\n数据\n数据\n\n

操作码可选值:event/data/retry/id

数据结束必须两个\n,此时服务器会关闭当前连接。

SSE

要求:

浏览器必须支持EventSource

服务端需要响应指定格式的数据

注意:

在使用Controller的时候,如果直接用return返回数据,那么连接会被web容器自动关闭,浏览器会重新建立连接,这种情况浏览器任然在与浏览器频繁建立连接,造成资源浪费。要解决这个问题,可以用HttpServletResponse.write(...)进行数据返回。

优点:

  • 减少建立连接
  • 支持自动重连
  • 实时性高

缺点:

  • 只能传输文本
  • 实现稍显复杂
  • IE全系不支持

4. Websocket

websocket也是H5提出的全双工协议,可以做到真正的客户端与服务端双向通信。

建立连接

Websocket Connection

请求头

Websocket Request Header

响应头

Websocket Response Header

优点:

  • 真正做到双向通信
  • 实时性高
  • 基于消息的文本或二进制通信

缺点:

  • 新协议,后端需要单独实现
  • 并不是所有浏览器都支持

后记

在实际工作中,如果对浏览器兼容性需求较高,并且实时性要求也较高,长轮询是比较合适的选择。对于实时性要求很高的场景,选择websocket或者SSE,但是需要注意的是SSE只支持文本传输。短轮询在一些实时性要求不是非常高,且用户量不大的情况下,从实现难易程度上是较好的选择。

没有最好的方案,只有最合适的方案。

posted @ 2020-07-02 23:50  六月瓜  阅读(192)  评论(0编辑  收藏  举报