構建通用WebSocket推送網關的設計與實踐

HTTP協議是一種無狀態的、基於TCP的請求/響應模式的協議,請求只能由客戶端發起、服務端進行響應。在大多數場景,這種請求/響應的Pull模式已經可以滿足需求。但在某些情形,例如消息推送、通知等應用場景,需要實時將數據同步到客戶端,這就要求服務端支持主動Push數據。

服務端推送技術歷史悠久,經歷了短輪詢、長輪詢的發展,一定程度上能夠解決問題,但也存在着不足,例如時效性、資源浪費等。HTML5標準帶來的WebSocket規範基本結束了這一局面,成爲目前服務端推送技術的主流方案。

在系統中集成WebSocket十分簡單,相關討論與資料很豐富。但如何實現一個通用的WebSocket推送網關尚未有成熟的方案。目前的雲服務廠商主要關注iOS和安卓等移動端推送,也缺少對WebSocket的支持。本文介紹了我們基於Netty實現WebSocket長連接網關時的一些思考和經驗。

1 愛奇藝號WebSocket使用現狀

愛奇藝號是愛奇藝內容創作、分發和變現的平臺,涵蓋自媒體、網大、網劇、兒童、知識、紀錄片等多個業務,是愛奇藝內容生態的重要組成。愛奇藝號作爲前臺系統,對用戶體驗有較高要求,直接影響着創作者的創作熱情。目前,愛奇藝號有多個業務場景中用到了WebSocket推送技術,包括:

  • 用戶評論。實時的將評論消息推送到瀏覽器。


  • 實名認證。合同簽署前需要對用戶進行實名認證,用戶掃描二維碼後進入第三方的認證頁面,認證完成後異步通知瀏覽器認證的狀態。


  • 活體識別。類似實名認證,當活體識別完成後,異步將結果通知瀏覽器。


在實際的業務開發中,我們發現,WebSocket推送技術在使用中存在以下問題:首先,WebSocket技術棧不統一,既有基於Netty實現的,也有基於Web容器實現的,給開發和維護帶來困難;其次,WebSocket實現分散在在各個工程中,與業務系統強耦合,如果有其他業務需要集成WebSocket,面臨着重複開發的窘境,浪費成本、效率低下;第三,WebSocket是有狀態協議的,客戶端連接服務器時只和集羣中一個節點連接,數據傳輸過程中也只與這一節點通信。

因此,WebSocket集羣需要解決會話共享的問題。如果只採用單節點部署,雖然可以避免這一問題,但無法水平擴展支撐更高負載,有單點的風險;最後,缺乏監控與報警,雖然可以通過Linux的Socket連接數大致評估WebSocket長連接數,但數字並不準確,也無法得知用戶數等具有業務含義的指標數據;無法與現有的微服務監控整合,實現統一監控和報警。

2 長連接網關的設計與實現

爲了解決以上問題,我們實現了統一的WebSocket長連接網關,具備如下特點:

1. 集中實現長連接管理和推送能力。統一技術棧,將長連接作爲基礎能力沉澱,便於功能迭代和升級維護。

2. 與業務解耦。將業務邏輯與長連接通信分離,使業務系統不再關心通信細節,也避免了重複開發,浪費研發成本。

3. 使用簡單。提供HTTP推送通道,方便各種開發語言的接入。業務系統只需要簡單的調用,就可以實現數據推送,提升研發效率。

4. 分佈式架構。實現多節點的集羣,支持水平擴展應對業務增長帶來的挑戰;節點宕機不影響服務整體可用性,保證高可靠。

5. 多端消息同步。允許用戶使用多個瀏覽器或標籤頁同時登陸在線,保證消息同步發送。

6. 多維度監控與報警。自定義監控指標與現有微服務監控系統打通,出現問題時可及時報警,保證服務的穩定性。

2.1. 技術選型
在衆多的WebSocket實現中,從性能、擴展性、社區支持等方面考慮,最終選擇了Netty。Netty是一個高性能、事件驅動、異步非阻塞的網絡通信框架,在許多知名的開源軟件中被廣泛使用。

WebSocket是有狀態的,無法像直接HTTP以集羣方式實現負載均衡,長連接建立後即與服務端某個節點保持着會話,因此集羣下想要得知會話屬於哪個節點,有兩種方案,一種是使用類似微服務的註冊中心來維護全局的會話映射關係,一種是使用事件廣播由各節點自行判斷是否持有會話,兩種方案對比如表1所示。

方案

優點

缺點

註冊中心

會話映射關係清晰,集羣規模較大時更合適

實現複雜,強依賴註冊中心,有額外運維成本

事件廣播

實現簡單更加輕量

節點較多時,所有節點均被廣播,資源浪費

表1:WebSocket集羣方案

綜合考慮實現成本與集羣規模,選擇了輕量級的事件廣播方案。實現廣播可以選擇基於RocketMQ的消息廣播、基於Redis的Publish/Subscribe、基於ZooKeeper的通知等方案,其優缺點對比如表2所示。從吞吐量、實時性、持久化、實現難易等方面考慮,最終選擇了RocketMQ。

方案

優點

缺點

基於RocketMQ

吞吐量高、高可用、保證可靠

實時性不如Redis

基於Redis

實時性高、實現簡單

不保證可靠

基於ZooKeeper

實現簡單

寫入性能較差,不適合頻繁寫入場景

表2:廣播的實現方案對比

2.2. 系統架構
網關的整體架構如圖1所示。

圖1:WebSocket長連接網關架構

網關的整體流程如下:

1. 客戶端與網關任一節點握手建立起長連接,節點將其加入到內存維護的長連接隊列。客戶端定時向服務端發送心跳消息,如果超過設定的時間仍沒有收到心跳,則認爲客戶端與服務端的長連接已斷開,服務端會關閉連接,清理內存中的會話。

2. 當業務系統需要向客戶端推送數據時,通過網關提供的HTTP接口將數據發向網關。

3. 網關在接收到推送請求後,將消息寫入RocketMQ。

4. 網關作爲消費者,以廣播模式消費消息,所有節點都會接收到消息。

5. 節點接收到消息後判斷推送的消息目標是否在自己內存中維護的長連接隊列裏,如果存在則通過長連接推送數據,否則直接忽略。

網關以多節點方式構成集羣,每節點負責一部分長連接,可實現負載均衡,當面對海量連接時,也可以通過增加節點的方式分擔壓力,實現水平擴展。同時,當節點出現宕機時,客戶端會嘗試重新與其他節點握手建立長連接,保證服務整體的可用性。

2.3. 會話管理
長連接建立起來後,會話維護在各節點的內存中。SessionManager組件負責管理會話,內部使用了哈希表維護了UID與UserSession的關係;UserSession代表用戶維度的會話,一個用戶可能會同時建立多個長連接,因此UserSession內部同樣使用了一個哈希表維護Channel與ChannelSession的關係。爲了避免用戶無限制的創建長連接,UserSession在內部的ChannelSession超過一定數量後,會將最早建立的ChannelSession關閉,減少服務器資源佔用。SessionManager、UserSession、ChannelSession的關係如圖2所示。

圖2:SessionManager組件

2.4. 監控與報警
爲了瞭解集羣建立了多少長連接、包含了多少用戶,網關提供了基本的監控與報警能力。網關接入了Micrometer,將連接數與用戶數作爲自定義指標暴露,供Prometheus進行採集,實現了與現有的微服務監控系統打通。在Grafana中方便地查看連接數、用戶數、JVM、CPU、內存等指標數據,瞭解網關當前的服務能力與壓力。報警規則也可以在Grafana中配置,當數據異常時觸發奇信(內部報警平臺)報警。

2.5. 性能壓測
壓測選擇兩臺配置爲4核16G的虛擬機,分別作爲服務器和客戶端。壓測時選擇爲網關開放了20個端口,同時建立20個客戶端,每個客戶端使用一個服務端端口建立起5萬連接,可以同時創建百萬個連接。連接數與內存使用情況如圖3所示。


圖3:百萬級連接

給百萬個長連接同時發送一條消息,採用單線程發送,服務器發送完成的平均耗時在10s左右,如圖4所示。

圖4:服務器推送耗時

一般同一用戶同時建立的長連接都在個位數。以10個長連接爲例,在併發數600、持續時間120s條件下壓測,推送接口的TPS大約在1600+,如圖5所示。

圖5 :長連接10、併發600、持續時間120s的壓測數據

當前的性能指標已滿足愛奇藝號的實際業務場景,可支持未來的業務增長。

3 業務案例

爲了更生動的說明優化效果,文章最後,我們也以封面圖添加濾鏡效果爲例,介紹一個愛奇藝號使用WebSocket網關的案例。

愛奇藝號自媒體發表視頻時,可選擇爲封面圖添加濾鏡效果,引導用戶提供提供更優質的封面。當用戶選擇一個封面圖後,會提交異步的後臺處理任務。當異步任務處理完成後,通過WebSocket將不同濾鏡效果處理後的圖片返回給瀏覽器,業務場景如圖6所示。

圖6:愛奇藝號視頻封面圖濾鏡

從研發效率方面考慮,如果在業務系統中集成WebSocket,至少需要1-2天的開發時間;如果直接使用網關的推送能力,只需要簡單的接口調用就實現了數據推送,開發時間降低到分鐘級別,研發效率大大提高。從運維成本方面考慮,業務系統不再含有與業務邏輯無關的通信細節,代碼的可維護性更強,系統架構變得更加簡單,運維成本大大降低。

4 寫在最後

WebSocket是目前實現服務端推送的主流技術,恰當使用能夠有效提供系統響應能力,提升用戶體驗。通過WebSocket長連接網關可以快速爲系統增加數據推送能力,有效減少運維成本,提高開發效率。

長連接網關的價值在於它封裝了WebSocket通信細節,與業務系統解耦,使得長連接網關與業務系統可獨立優化迭代,避免重複開發,便於開發與維護。其次,網關提供了簡單易用的HTTP推送通道,支持多種開發語言接入,便於系統集成和使用。另外,網關採用了分佈式架構,可以實現服務的水平擴容、負載均衡與高可用。最後,網關集成了監控與報警,當系統異常時能及時預警,保證服務的健康和穩定。
 
目前,WebSocket長連接網關已在愛奇藝號圖片濾鏡結果通知、MCN電子簽章等多個業務場景中得到應用。未來還有許多方面需要探索,例如消息的重發與ACK、WebSocket二進制數據的支持、多租戶的支持等。我們也會不斷優化、豐富功能,帶給開發者更好的使用體驗。

也許你還想看

愛奇藝知識WEB前端組件化實踐

一切數據皆可配置:愛奇藝海外站的運營後臺設計實踐


 掃一掃下方二維碼,更多精彩內容陪伴你!

本文分享自微信公衆號 - 愛奇藝技術產品團隊(iQIYI-TP)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章