背景

在读最新的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使用的是非阻塞式的。