Spring 4.0的一个最大更新是增加了websocket的支持。websocket提供了一个在web应用中的高效、双向的通讯,需要考虑到客户端(浏览器)和服务器之间的高频和低延时消息交换。一般的应用场景有:在线交易、网页聊天、游戏、协作、数据可视化等。
-
1、Web消息通信总结
以一个简单的网页聊天为应用场景,在Java EE环境下,其实现方式大抵有以下几种:
轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。 其主要用到js的setInterval()方法。
优点:简单易懂,后端程序编写比较容易,不需要特别编写特别的代码。
缺点:请求中有大半是无用,同时浪费带宽和服务器资源。
实例:适于小型应用。
长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
实例:WebQQ、Hi网页版、Facebook IM。
长连接:在页面里嵌入一个隐蔵iframe,将这个隐蔵iframe的src属性设为对一个长连接的请求或是采用xhr请求,服务器端就能源源不断地往客户端输入数据。
优点:消息即时到达,不发无用请求;管理起来也相对方便。
缺点:服务器维护一个长连接会增加开销。
实例:Gmail聊天
Flash Socket:在页面中内嵌入一个使用了Socket类的 Flash 程序JavaScript通过调用此Flash程序提供的Socket接口与服务器端的Socket接口进行通信,JavaScript在收到服务器端传送的信息后控制页面的显示。
优点:实现真正的即时通信,而不是伪即时。
缺点:客户端必须安装Flash插件;非HTTP协议,无法自动穿越防火墙。
实例:网络互动游戏。
传统 Web 模式在处理高并发及实时性需求的时候,会遇到难以逾越的瓶颈,随着连接数的增多,服务器资源将很快被耗尽,因此一种新的规范随之诞生,websocket是在物理层非网络层建立一条客户端至服务器的长连接,以此来保证服务器向客户端的即时推送,既不耗费线程资源,又不会不断向服务器轮询请求。
2、WebSocket机制
WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:
- WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
- WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。
非 WebSocket 模式传统 HTTP 客户端与服务器的交互如下图所示:
而与传统HTTP通信相比,WebSocket的模式如下:
从上可以看出,在连接生效过后,Server端可以实现向Browser端主动的消息推送。一旦 WebSocket 连接建立后,后续数据都以帧序列的形式传输。在客户端断开 WebSocket 连接或 Server 端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。
而HTTP与WebSocket的通信交互过程中的报文也有所区别:
WebSocket Request部分报文:
Host:localhost:8080
Origin:http://localhost:8080
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:39rBeP3SAnLxTYggKvOcSg==
Sec-WebSocket-Version:13
Upgrade:websocket
可以看到,客户端发起的 WebSocket 连接报文类似传统 HTTP 报文,”Upgrade:websocket”参数值表明这是 WebSocket 类型请求,“Sec-WebSocket-Key”是 WebSocket 客户端发送的一个 base64 编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error during WebSocket handshake”错误,并关闭连接。
WebSocket Response部分报文:
Connection:upgrade
Date:Fri, 06 May 2016 07:00:18 GMT
Sec-WebSocket-Accept:U9tI2JJDzgtcvS55TRoT816bBYA=
Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits=15
Server:Apache-Coyote/1.1
Upgrade:websocket
“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1 101 Switching Protocols”表示服务端接受 WebSocket 协议的客户端连接,经过这样的请求-响应处理后,客户端服务端的 WebSocket 连接握手成功, 后续就可以进行 TCP 通讯了。读者可以查阅WebSocket 协议栈了解 WebSocket 客户端和服务端更详细的交互数据格式。