Tomcat NIO(18)-服务端事件SSE

上一篇文章中我们主要介绍 tomcat nio 中的流式上传文件,其本质是直接拿到上传文件的网络输入流,然后在应用程序中读取并操作。避免了以磁盘作为中转,从而提高了效率。这里我们主要介绍服务端事件 SSE。

SSE 的简称是 Server-Sent Events,其本质是浏览器发送一个请求到服务端建立一个长连接,在这个长连接基础上客户端多次发送 http 请求,来轮询服务端是否有数据需要返回给浏览器。所以 SSE 是建立在浏览器和服务端长连接基础上的多次 http 轮询请求,但是 SSE 支持断开重连(由浏览器自己实现),简化了连接关闭情况下操作,但是 SSE 对浏览器和服务器都有要求:

  • 浏览器要支持 SSE,这一点基本支持 html5 的浏览器都可以。

  • 服务器端要支持长连接,因为 SSE 是基于长连接的。

  • 服务端返回数据 content-type 要为 text/event-stream。

  • 服务端返回数据要以 data: 开头,以\n\n 结尾的格式才能被解析。

下面我们示例简单的服务端代码和客户端代码:

@GetMapping(path="/test-sse", produces="text/event-stream;charset=UTF-8")
@ResponseBody
public String testServerSentEvent(HttpServletRequest request) throws Exception{
    Thread.sleep(300);
    //Logic to impl here
    return "data:"+ Math.random()+"\n\n";
}


<!DOCTYPE html>
<html>
<head> 
<title>Test SSE Page</title>
</head>
<script type="text/javascript">
var source = new EventSource('http://127.0.0.1:1033/basic-service/test-controller/test-sse');
    source.onmessage = function(event){
    console.info(event.data);
    document.getElementById('result').innerText=event.data;
}
</script>
<body class="blank">
<div id="result"></div>
</body>
</html>


  • 服务端代码只是 sleep 当前线程 300 毫秒,然后返回随机数。

  • 客户端代码利用 EventSource SSE API 对象调用服务端,并显示返回的随机数。

SSE运行效果:

  • 由上图发现,SSE 的浏览器端会不间断的发请求来轮询服务端。

  • 请求头和响应头中的 content-type 项都是 text/event-stream 类型。

  • 响应体就是我们的数据,用 event.data 可以取到并加以显示。

SSE基于长连接

  • 查看网络连接状态,发现浏览器端用的62672端口和服务端的1033端口通信。

  • 我们多次查看(这里是2次),发现连接始终不变,所以SSE是基于长连接的。

  • 根据以前文章,对于 tomcat 来说,一个长连接默认最多支持100个请求,所以当请求多于100个的时候,一定关闭当前连接,然后由 SSE 再次建立另一个长连接。

  • 上图就是请求超过100个的情况,我们发现浏览器的62672端口连接出现了 time_wait 状态,说明是浏览器主动关闭连接,发起 tcp 关闭的4次挥手。然后在浏览器端出现了62884端口新的连接,说明 SSE 又自动建立了新的长连接。

  • 过一段时间再次查看如上图,发现 time_wait 状态的连接消失回收,只有新的62884端口的长连接,符合 tcp time_wait 需要等待 2MSL 的回收策略。

客户端主动关闭:

细心的同学可能发现,不是说 tomcat 默认长连接超过100个请求就会关闭么,但是主动关闭方的 time_wait 却出现在浏览器端,这是为什么呢。

  • 上图可以发现在默认长连接超过100个请求的时候,tomcat 返回给浏览器的响应头里有 Connection: close项。

  • 根据 http 标准,浏览器接到这个响应头之后,就发起了对这个长连接的关闭,所以主动关闭的 time_wait 状态在浏览器端。

  • 还可以间接证明,tomcat 默认长连接超过100个请求的时候,就会返回给客户端 Connection: close 的响应头,由客户端根据这个响应头实现关闭。当然返回这个响应头之后,tomcat 也会主动关闭服务端的 socket。

对于 SSE 总结如下:

  • SSE 需要浏览器本身的支持,只要支持 html5 的浏览器都可以。

  • SSE 对于服务端需要支持长连接。

  • SSE 对于请求头和响应头都应该是 text/event-stream 类型。

  • SSE 要求服务端返回数据以 data: 开头,以\n\n 结尾。

  • SSE是基于一个长连接的多次 http 请求轮询。

  • SSE支持长连接关闭之后的自动重连。

目前先写到这里,下一篇文章里我们继续介绍 tomcat 中的异步请求。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值