SSE协议介绍

SSE协议的全称是Server-Send Events,专门用于服务端实时推送消息。

SSE是基于HTTP协议,通过长连接的方式持续获取消息。也就是客户端建立TCP链接后,向服务端发起一个HTTP请求,服务端接收到请求后把要返回的内容,按照事件流的方式,不断推送给客户端。跟下载文件一样,所有内容推送完了,连接才关闭。

SSE协议本质上是对HTTP返回的内容进行了约定,客户端按照约定进行解析。

协议的优缺点

SSE协议和websocket协议都可以用作服务端推送,相对于websocket协议的优势有:

  1. 基于http协议,主流浏览器都支持
  2. 轻量级协议
  3. 可以定制消息类型
  4. 支持超时重连

也有一些不足:

  1. 服务端单向推送消息,不是全双工可以双向通信
  2. 协议不支持二进制传输,需要使用方把现在转成二进制格式

协议格式

协议头

SSE协议返回的是事件流,需要指定内容类型。并且,协议是长连接,也要开启长连接和禁止缓存内容。所以要在HTTP header里加上这3个信息:

  1. Content-Type:text/event-stream
  2. Connection:keep-alive
  3. Cache-Control:no-cache

协议内容

协议内容放在http返回的body里,每次返回一个Event信息。每个Event里可以包含5个属性:

  1. id
  2. event
  3. data
  4. retry
  5. :(注释消息)

每个属性值占用一行,每行的内容都是由属性名称+属性值组成+换行符,之间用冒号隔开(:)。连个消息之间用额外的换行符区分。

// 这是服务端返回的两条消息
id:1
data:你
data:好,

id:2
event: question
data:你的
data:名字叫什么?

属性介绍

id字段

id用于表示Event的序号,客户端通过序号实现断线重连功能。需要重连的时候,客户端在HTTP的header里加一个Last-Event-ID字段,把最后接收到的id传给服务端。服务端实现了重连功能,就能继续传Last-Event-ID之后的消息给客户端。

event字段

event表示自定义事件类型,客户端通过该字段区分不同消息。

id:2
event: question
data:你的
data:名字叫什么?

data字段

data表示返回的业务数据,如果数据很长可以分成多行返回。

id:1
data:你
data:好,

retry字段

retry表示重连的间隔,以毫秒为单位。

id:1
retry:30000
data:你
data:好,

:(注释消息)

需要返回注释消息的时候,格式是以冒号开头,后面接注释信息

id:1
data:你
data:好,
:这是注释信息

Spring实现SSE接口

spring webmvc已经支持了SSE协议,要返回这是一个简单的SSE接口示例,会返回3条消息:

@GetMapping(value = "/sse")
public SseEmitter sse(HttpServletResponse response) {
    response.setCharacterEncoding("UTF-8");

    SseEmitter sseEmitter = new SseEmitter();
    sseEmitter.onCompletion(() -> System.out.println("complete"));

    new Thread(() -> {
        for (int i = 1; i <= 3; i++) {
            try {
                Set<ResponseBodyEmitter.DataWithMediaType> body = SseEmitter.event()
                        .id(String.valueOf(i))
                        .name("custom-" + i)
                        .data("你好:" + i)
												.data("我叫AA" + i)
                        .comment("这是注释内容")
                        .reconnectTime(5000)
                        .build();
                sseEmitter.send(body);
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 断开连接
        sseEmitter.complete();
    }).start();
    return sseEmitter;
}

这里做了几件事:

  1. 通过SseEmitter对象返回事件流,这是时会在响应头里自动加上Content-Type: text/event-stream、Connection: keep-alive信息
  2. 事件流结束后调用sseEmitter.complete()关闭连接
  3. 使用onCompletion方法监听连接关闭消息
  4. 通过HttpServletResponse来设置返回的编码为UTF-8,最终返回的header是Content-Type: text/event-stream;charset=UTF-8

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李昂的数字之旅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值