Spring WebSocket詳解
Spring架構從4.0版開始支援WebSocket,下面我将詳述Spring WebSocket庫的相關内容。内容包括Spring架構是如何在Web應用中支援WebSocket方式的消息通信,以及如何利用STOMP協定作為應用層的協定——WebSocket的子協定。
1、WebSocket協定介紹
WebSocket協定是RFC-6455規範定義的一個Web領域的重要的功能:全雙工,即用戶端和伺服器之間的雙向通信。它是一個令人興奮的功能,業界在此領域上已經探索很久,使用的技術包括Java Applet、XMLHttpRequest、Adobe Flash、ActiveXObject、各種Comet技術、伺服器端的發送事件等。
需要了解一點,在使用WebSocket協定前,需要先使用HTTP協定用于建構最初的握手。這依賴于一個機制——建立HTTP,請求協定更新(或叫協定轉換)。當伺服器同意後,它會響應HTTP狀态碼101,表示同意切換協定。假設通過TCP套接字成功握手,HTTP協定更新請求通過,那麼用戶端和伺服器端都可以彼此互發消息。
Spring架構4.0以上版本引入了一個新子產品,即spring-websocket子產品。它對WebSocket通信提供了支援。它相容Java WebSocket API規範JSR-356,同時提供了額外的功能
2、WebSocket的降級選項
浏覽器對WebSocket的支援并不快,IE浏覽器是第10版才開始支援的。此外,一些代理工具也會限制WebSocket通信。是以,即使是現在要開發WebSocket應用,降級選項是必不可少的,以便在不支援的場景使用模拟WebSocket API的工作方式。Spring架構提供了這種透明的降級方案——使用SockJS協定。此方案可以通過配置來自動切換,無需修改應用程式的代碼。
3、消息通信架構
使用WebSocket除了開發方面的挑戰外,還有一個難點在于設計上的考慮。
目前REST架構是一個廣泛接受、易于了解、适合建構現代Web應用的架構。REST架構依賴于很多URL、和幾個HTTP方法,使用了連結、保持無狀态等原則。
相比之下WebSocket應用可能隻使用一個URL用于最初的HTTP握手。随後所有的消息都共享此TCP連接配接,消息在此連接配接上雙向流動。這一點可見,它與REST架構是完全不同的,是異步的、事件驅動的、消息傳遞的架構。WebSocket架構與傳統的消息傳輸方案(如JMS、AMQP)比較相似。
Spring架構4.0引入了一個新子產品——spring-messaging子產品,它包含了很多來自于Spring Integration項目中的概念抽象,比如:Message消息、消息頻道MessageChannel、消息句柄MessageHandler等。此子產品還包括了一套注釋,可以把消息映射到方法上,與Spring MVC基于注釋的程式設計模型相似。
4、WebSocket支援子協定
WebSocket隻是一個消息傳遞的體系結構,它沒有指定任何特定的消息傳遞協定。它是一個TCP協定之上的超薄層,可以把位元組流轉換成消息流(文本貨二進制)。随後由應用程式來解釋消息。
與HTTP協定不同,WebSocket協定隻是一個應用級的協定,它非常簡單,并不能了解傳入的消息,也不能對消息進行路由或處理。是以WebSocket協定是應用級協定的底層,其上需要一個架構來了解和處理消息。
出于這個原因,WebSocket RFC定義了子協定的使用。在握手過程中,用戶端和伺服器端可以使用Header部分的Sec-WebSocket-Protocol來協商使用的子協定——也即使用更進階的應用級協定。子協定的使用不是必須的,但即使不使用子協定,應用程式仍然需要選擇一個消息格式——讓用戶端和伺服器互相可以了解的格式。這種格式可以自定義,或特定于架構,或使用标準的消息傳遞協定。
Spring架構提供了對使用STOMP子協定的支援。
STOMP,Streaming Text Orientated Message Protocol,流文本定向消息協定。STOMP是一個簡單的消息傳遞協定, 是一種為MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協定。
STOMP提供了一個可互操作的連接配接格式,允許STOMP用戶端與任意STOMP消息代理(Broker)進行互動,類似于OpenWire協定(一種二進制協定)。
5、什麼場景下該使用WebSocket
在Web應用中,用戶端和伺服器端需要以較高頻率和較低延遲來交換事件時,适合用WebSocket。是以WebSocket适合财經、遊戲、協作等應用場景。
對于其他應用場景則未必适合。例如,某個新聞訂閱需要顯示突發新聞,使用間隔幾分鐘的長輪詢也是可以的,這裡的延遲可以接受。
即使在要求低延遲的應用場景,如果傳輸的消息數很低(比如監測網絡故障的場景),那麼應該考慮使用長輪詢技術。
而隻有在低延遲和高頻消息通信的場景下,選用WebSocket協定才是非常适合的。即使是這樣的應用場景,仍然存在是選擇WebSocket通信呢?又或者是選擇REST HTTP通信呢?
答案是會根據應用程式的需求而定。但是,也可能同時使用這兩種技術,把需要頻繁交換的資料放到WebSocket中實作,而把REST API作為過程性的業務的實作技術。另外,當REST API的調用中需要把某個資訊廣播給多個用戶端是,也可以通過WebSocket連接配接來實作。
Spring架構提供了@Controller注釋和@RestController注釋,兩者都可以用于HTTP請求的處理以及WebSocket消息的處理。另外,Spring MVC的請求處理方法,或其它應用程式的請求處理方法,都可以很容易地使用WebSocket協定來廣播消息到所有感興趣的用戶端或指定使用者。