背景
在读最新的spring5文档,会发现websocket分布在两个不同的模块: Web Servlet模块 web Reactive模块 同一个东西为什么在两个模块都有呢? 最初怀疑是不是spring的bug,于是就针对两个不同模块的websocket进行研读,发现也不是很清晰,那么怎么弄懂他们的区别呢?
什么是Websocket?
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 websocket产生的背景 很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。 而比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。 在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
Spring Websocket分析
因websocket是cs结构,那么我们分别从client和server端来分析,就容易看出他们的差异了。
- Web Servlet模块的 WebSocket Client
WebSocketClient client =new WebSocketClient();
- Web Reactive模块的websocket client
WebSocketClient client = new ReactorNettyWebSocketClient();
- Web Servlet模块的 WebSocket Server
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
public class MyHandler extends TextWebSocketHandler {
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
// ...
}
}
- Web Reactive模块的websocket server
class ExampleHandler implements WebSocketHandler {
@Override
public Mono<Void> handle(WebSocketSession session) {
Flux<WebSocketMessage> output = session.receive()
.doOnNext(message -> {
// ...
})
.concatMap(message -> {
// ...
})
.map(value -> session.textMessage("Echo " + value));
return session.send(output);
}
}
从上面可以看到, Web Servlet模块WebSocket的client使用的是普通的WebSocketClient,而Web Reactive模块的websocket的client利用了ReactorNettyWebSocketClient的Reactive特性。
Web Servlet模块WebSocket的server使用的是普通的WebSocketHandler,而Web Reactive模块的websocket的server利用了Flux的Reactive特性。
总结
Web Servlet模块的 WebSocket的client和server使用的是阻塞式的。 Web Reactive模块的websocket的client和server使用的是非阻塞式的。