深入Sever-Sent Events

Server-Sent Events(SSE)实现了服务器向浏览器单向推送消息的能力,前面文章有提到过,今天这里来详细讲解下。

SSE是什么

SSE设计了两个新东西

  • EventSource接口
  • “事件流”数据格式

EventSource接口详解

整个SSE在浏览器端的API,就如上5个,非常简单,但是为我们实现了大量的细节功能。

例如连接意外断开后,浏览器会自动重连,并发送上一次的消息ID,便于服务端重传丢失的消息和恢复数据流。

“事件流”协议

下面是一个SSE事件流的HTTP报文

里面有几个关键点:

  • 请求头
    • 带上Accept: text/event-stream
  • 响应头
    • 带上Content-type: text/events-stream
    • 带上Transfer-Encoding: chunked
  • 响应内容
    • retry 连接意外断开后,浏览器重新发起连接的时间间隔
    • data 消息的有效载荷,可以是普通字符串类型,或者是JSON对象
    • event 事件类型
    • id 可以用来标记消息序号,便于重连后能恢复数据流,重连时会带上Last-Event-ID来帮助恢复事件流
    • \n\n 用来分割每条消息边界

SSE额外注意事项

SSE所定义的“事件流”格式,让不支持的SSE的浏览器,可以通过XHR模拟来优雅降级。

SSE的数据为UTF-8数据,不支持二进制流,但是支持使用服务端的Gzip进行体积压缩。

SSE的“事件流”格式,已经定义了id作为消息序号,不需要业务在消息的内容中再次定义。

SSE使用场景

例如各种Dashboard的实时采集量反馈

例如实时投票结果等

利用H5的EventSource,小试服务器推送(SSE)

H5在最后定稿的时候,出现了一个新的JS API:EventSource(也许是我之前一直没关注吧)。

EventSource有什么用呢?简单来说,就是实现Web端的服务器主动推送功能(SSE,Server-Sent-Events)。

废话少说,先上一段代码:

这段代码运行后,会开始监听服务器推送的事件,例如任意时刻,sse.php输出一句hello world,客户端的console就会立马有输出。

我们来深入了解一下。

窥探EventSource细节:

首先, new EventSource(url) ,客户端会立马向该url发出一个HTTP请求(没错,的确是HTTP请求,整个SSE都是建立在HTTP协议上面的,这是于WebSocket的本质区别),然后观察这个HTTP的Header,它的MIME类型是text/event-stream。

text/event-stream是专门为SSE设计的MIME类型,这个是构造SSE请求的关键。

当服务端收到接到请求后,会hold住这个请求,当需要服务端推送数据的时候,才往这个请求中返回所需要的信息,以 data:'这个是返回的消息内容' 格式的写入,并利用HTTP/1.1中的分块传输的机制,立马刷新缓存中,输出内容并不释放连接,当有下一个内容需要推送的时候,又立马扔到HTTP的返回中。

上面的流程是不是很熟息?和以前的长连接的玩法很像?SSE就是把原来的HTTP长连接的玩法给标准化了。

继续阅读“利用H5的EventSource,小试服务器推送(SSE)”