Web端即時通訊實踐乾貨:如何讓WebSocket斷網重連更快速?

2021-01-15 即時通訊技術分享

本文作者網易智慧企業web前端開發工程師馬瑩瑩。為了提升內容質量,收錄時有修訂和改動。

1、引言

在一個完善的即時通訊IM應用中,WebSocket是極其關鍵的一環,它為基於Web的即時通訊應用提供了一種全雙工的通信機制。但為了提升IM等實際應用場景下的消息即時性和可靠性,我們需要克服WebSocket及其底層依賴的TCP連接對於複雜網絡情況下的不穩定性,即時通訊的開發者們通常都需要為其設計一套完整的連接保活、驗活以及斷片網重連方案。

就斷網重連而言,其重連響應速度將嚴重影響了上層應用的「即時性」和用戶體驗。試想打開網絡一分鐘後,微信的網絡不能即時感知到socket連接的恢復,無法即時收發聊天消息的話,是不是很崩潰?

因此,如何在複雜網絡場景下,更即時快速地感知網絡變動,並快速恢復WebSocket的可用性,就變得尤為重要。本文將基於筆者的開發實踐,分享WebSocket在不同狀態下、不同的網絡狀態下,應該如何實現快速斷網重連。

* 閱讀對象:本文適合有過IM底層網絡實際開發經驗,或者對底層網絡實現有較深了解的開發者閱讀。如果對底層網絡了解甚少,建議跳過本文,直接閱讀網絡本文末尾附錄部分的基礎後再回頭來看。

* 內容點評:本文內容沒有高大上,但比較乾貨,實用性較高,內容也很通俗,建議可詳細閱讀。文中雖講的是WebSocket,但思想可以延伸應用到基於TCP協議的同類技術中。

本文已同步發布於「即時通訊技術圈」公眾號。

2、預備知識

本文中將要分享的內容是基於實踐總結,如果你對Web端的即時通訊知識還一頭霧水,務必先讀:《新手入門貼:史上最全Web端即時通訊技術原理詳解》、《Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE》。

限於篇幅,本文不會深究WebSocket技術細節,如有興趣請系統學習:

《新手快速入門:WebSocket簡明教程》《WebSocket詳解(一):初步認識WebSocket技術》《WebSocket詳解(二):技術原理、代碼演示和應用案例》《WebSocket詳解(三):深入WebSocket通信協議細節》《WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)》《WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)》《WebSocket詳解(六):刨根問底WebSocket與Socket的關係》3、快速了解WebSocket

Websocket誕生於2008年,在2011年成為國際標準,現在所有的瀏覽器都已支持(詳見《新手快速入門:WebSocket簡明教程》)。它是一種全新的應用層協議,是專門為web客戶端和服務端設計的真正的全雙工通信協議,可以類比HTTP協議來了解websocket協議。

(圖片引用自《WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)》)

它們的不同點:

1)HTTP的協議標識符是http,WebSocket的是ws;2)HTTP請求只能由客戶端發起,伺服器無法主動向客戶端推送消息,而WebSocket可以;3)HTTP請求有同源限制,不同源之間通信需要跨域,而WebSocket沒有同源限制。它們的相同點:

1)都是應用層的通信協議;2)默認埠一樣,都是80或443;3)都可以用於瀏覽器和伺服器間的通信;4)都基於TCP協議。兩者和TCP的關係圖:

(圖片引用自《新手快速入門:WebSocket簡明教程》)

有關Http和WebSocket的關係,可以詳讀:

《WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)》《WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)》有關WebSocket和Socket的關係,可以詳讀:《WebSocket詳解(六):刨根問底WebSocket與Socket的關係》.

4、WebSocket重連過程拆解

首先考慮一個問題,何時需要重連?

最容易想到的是WebSocket連接斷了,為了接下來能收發消息,我們需要再發起一次連接。

但在很多場景下,即便WebSocket連接沒有斷開,實際上也不可用了。

比如以下場景:

1)設備切換網絡;2)鏈路中間路由崩潰(常識是一條socket連接對應的網絡通路上,會存在很多路由設備);3)鏈路的前端出口不可用(比如家庭WiFi中,網絡連接正常,但實際運營商的寬帶已經欠費被停機);4)伺服器負載持續過高無法響應等。這些場景下的WebSocket都沒有斷開,但對上層來說,都沒辦法正常的收發數據了。

因此在重連前,我們需要一種機制來感知連接是否可用、服務是否可用,而且要能快速感知,以便能夠快速從不可用狀態中恢復。

一旦感知到了連接不可用,那便可以棄舊圖新了,棄用並斷開舊連接,然後發起一次新連接。這兩個步驟看似簡單,但若想達到快,且不是那麼容易的。

首先:是斷開舊連接,對客戶端來說,如何快速斷開?協議規定客戶端必須要和伺服器協商後才能斷開WebSocket連接,但是當客戶端已經聯繫不上伺服器、無法協商時,如何斷開並快速恢復?

其次:是快速發起新連接。此快非彼快,這裡的快並非是立即發起連接,立即發起連接會對伺服器帶來不可預估的影響。重連時通常會採用一些退避算法,延遲一段時間後再發起重連。但如何在重連間隔和性能消耗間做出權衡?如何在「恰當的時間點」快速發起連接?

帶著這些疑問,我們來細看下這三個過程:

5、快速重連關鍵1:快速感知何時需要重連

5.1 場景

需要重連的場景可以細分為三種:

1)連接明確斷開了;2)連接沒斷但是不可用了;3)連接對端的服務不可用了。對於第一種場景:這很簡單,連接直接斷開了,肯定需要重連了。

對於後兩者:無論是連接不可用,還是服務不可用,對上層應用的影響都是不能再收發即時消息了。

5.2 心跳包主動探測網絡可用性

所以從上面這個角度出發,感知何時需要重連的一種簡單粗暴的方法就是通過心跳包超時:發送一個心跳包,如果超過特定的時間後還沒有收到伺服器回包,則認為服務不可用,如下圖中左側的方案(這種方法最直接)。

那如果想要快速感知呢,就只能多發心跳包,加快心跳頻率。但是心跳太快對移動端流量、電量的消耗又會太多,所以使用這種方法沒辦法做到快速感知,可以作為檢測連接和服務可用的兜底機制。

5.3 被動監聽網絡狀態改變

如果要檢測連接不可用,除了用心跳檢測,還可以通過判斷網絡狀態來實現,因為斷網、切換wifi、切換網絡是導致連接不可用的最直接原因,所以在網絡狀態由offline變為online時,大多數情況下需要重連下,但也不一定,因為webscoket底層是基於TCP的,TCP連接不能敏銳的感知到應用層的網絡變化,所以有時候即便網絡斷開了一小會,對WebSocket連接是不會有影響的,網絡恢復後,仍然能夠正常地進行通信。

因此在網絡由斷開到連接上時,立即判斷下連接是否可用,可以通過發一個心跳包判斷,如果能夠正常收到伺服器的心跳回包,則說明連接仍是可用的,如果等待超時後仍沒有收到心跳回包,則需要重連,如上圖中的右側。這種方法的優點是速度快,在網絡恢復後能夠第一時間感知連接是否可用,不可用的話可以快速執行恢復,但它只能覆蓋應用層網絡變化導致WebSocket不可用的情況。

5.4 小結

綜上所述:

1)定時發送心跳包檢測的方案貴在穩定,能夠覆蓋所有場景,但速度不即時(心跳間隔是固定的);2)判斷網絡狀態的方案速度快,無需等待心跳間隔,較為靈敏,但覆蓋場景較為局限。因此,我們可以結合兩種方案:

1)定時以不太快的頻率發送心跳包,比如40s/次、60s/次等,具體可以根據應用場景來定;2)然後在網絡狀態由offline變為online時立即發送一次心跳,檢測當前連接是否可用,不可用的話立即進行恢復處理。這樣在大多數情況下,上層的應用通信都能較快從不可用狀態中恢復,對於少部分場景,有定時心跳作為兜底,在一個心跳周期內也能夠恢復。

6、快速重連關鍵2:快速斷開舊連接

通常情況下,在發起下一次連接前,如果舊連接還存在的話,應該先把舊連接斷開。

這樣做的目的:

1)一來可以釋放客戶端和伺服器的資源;2)二來可以避免之後誤從舊連接收發數據。我們知道WebSocket底層是基於TCP協議傳輸數據的,連接兩端分別是伺服器和客戶端,而TCP的TIME_WAIT狀態是由伺服器端維持的,因此在大多數正常情況下,應該由伺服器發起斷開底層TCP連接,而不是客戶端。

也就是說:

1)要斷開WebSocket連接時,如果是伺服器收到指示要斷開WebSocket,那它應該立即發起斷開TCP連接;2)如果是客戶端收到指示要斷開WebSocket,那它應該發信號給伺服器,然後等待底層TCP連接被伺服器斷開或直至超時。那如果客戶端想要斷開舊的WebSocket,可以分為WebSocket連接可用和不可用兩種情況來討論。

具體如下:

1)當舊連接可用時,客戶端可以直接給伺服器發送斷開信號,然後伺服器發起斷開連接即可;2)當舊連接不可用時,比如客戶端切換了wifi,客戶端發送了斷開信號,但是伺服器收不到,客戶端只能遲遲等待,直至超時才能被允許斷開。超時斷開的過程相對來說是比較久的,那有沒有辦法可以快點斷開?

上層應用無法改變只能由伺服器發起斷開連接這種協議層面的規則,所以只能從應用邏輯入手,比如在上層通過業務邏輯保證舊連接完全失效,模擬連接斷開,然後在發起新連接,恢復通訊。

這種方法相當於嘗試斷開舊連接不行時,直接棄之,然後就能快速進入下一流程,所以在使用時一定要確保在業務邏輯上舊連接已完全失效。

比如:

1)保證丟掉從舊連接收到所有數據;2)舊連接不能阻礙新連接的建立3)舊連接超時斷開後不能影響新連接和上層業務邏輯等等。7、快速重連關鍵3:快速發起新連接

有IM開發經驗的同學應該有所了解,遇到因網絡原因導致的重連時,是萬萬不能立即發起一次新連接的,否則當出現網絡抖動時,所有的設備都會立即同時向伺服器發起連接,這無異於黑客通過發起大量請求消耗網絡帶寬引起的拒絕服務攻擊,這對伺服器來說簡直是災難(即:服務端雪崩效應)。

所以在重連時通常採用一些退避算法,延遲一段時間再發起重連,如下圖中左側的流程。

如果要快速連上呢?最直接的做法就是縮短重試間隔,重試間隔越短,在網絡恢復後就能越快的恢復通訊。但是太頻繁的重試對性能、帶寬、電量的消耗就比較嚴重。

如何在這之間做一個較好的權衡呢?

1)一種比較合理的方式是隨著重試次數增多,逐漸增大重試間隔;2)另一方面監聽網絡變化,在網絡狀態由offline變為online這種比較可能重連上的時刻,適當地減小重連間隔。上述第2)種方案,如上圖中的右側所示,隨重試次數的增多,重連間隔也會變大。這兩種方式配合使用,更為合理。

除此之外,還可以結合業務邏輯,根據成功重連上的可能性適當的調整間隔,如網絡未連接時或應用在後臺時重連間隔可以調大一些,網絡正常的狀態下可以適當調小一些等等,加快重連上的速度。

8、本文小結

最後總結一下。

本文將WebSocket斷網重連邏輯細分為三個步驟:

1)確定何時需要重連;2)斷開舊連接;3)發起新連接。然後分別分析了在WebSocket的不同狀態下、不同的網絡狀態下,如何快速完成這個三個步驟。

過程具體總結就是:

1)首先:通過定時發送心跳包的方式檢測當前連接是否可用,同時監測網絡恢復事件,在恢復後立即發送一次心跳,快速感知當前狀態,判斷是否需要重連;2)其次:正常情況下由伺服器斷開舊連接,與伺服器失去聯繫時直接棄用舊連接,上層模擬斷開,來實現快速斷開;3)最後:發起新連接時使用退避算法延遲一段時間再發起連接,同時考慮到資源浪費和重連速度,可以在網絡離線時調大重連間隔,在網絡正常或網絡由offline變為online時縮小重連間隔,使之儘可能快地重連上。以上就是我關於如何實現WebSocket快速重連的技術分享,歡迎留言與我探討。

9、參考資料

[1] RFC 6455 文檔

[2] 新手快速入門:WebSocket簡明教程

[3] WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)

[4] WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)

[5] WebSocket詳解(六):刨根問底WebSocket與Socket的關係

附錄:更多Web端即時通訊資料

《新手入門貼:史上最全Web端即時通訊技術原理詳解》《Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE》《SSE技術詳解:一種全新的HTML5伺服器推送事件技術》《Comet技術詳解:基於HTTP長連接的Web端實時通信技術》《socket.io實現消息推送的一點實踐及思路》《LinkedIn的Web端即時通訊實踐:實現單機幾十萬條長連接》《Web端即時通訊技術的發展與WebSocket、Socket.io的技術實踐》《Web端即時通訊安全:跨站點WebSocket劫持漏洞詳解(含示例代碼)》《開源框架Pomelo實踐:搭建Web端高性能分布式IM聊天伺服器》《使用WebSocket和SSE技術實現Web端消息推送》《詳解Web端通信方式的演進:從Ajax、JSONP 到 SSE、Websocket》《MobileIMSDK-Web的網絡層框架為何使用的是Socket.io而不是Netty?》《理論聯繫實際:從零理解WebSocket的通信原理、協議格式、安全性》《微信小程序中如何使用WebSocket實現長連接(含完整源碼)》《八問WebSocket協議:為你快速解答WebSocket熱門疑問》《快速了解Electron:新一代基於Web的跨平臺桌面技術》《一文讀懂前端技術演進:盤點Web前端20年的技術變遷史》《Web端即時通訊基礎知識補課:一文搞懂跨域的所有問題!》《Web端即時通訊實踐乾貨:如何讓你的WebSocket斷網重連更快速?》>> 更多同類文章 ……

(本文同步發布於:http://www.52im.net/thread-3098-1-1.html)

相關焦點

  • 八問WebSocket協議:為你快速解答WebSocket熱門疑問
    本文將從8個常見的疑問入手,為還不了解WebSocket協議的開發者快速普及相關知識,從而節省您學習WebSocket的時間。另外,如果您對Web端的即時通訊技術還完全不了解,那麼《新手入門貼:詳解Web端即時通訊技術的原理》、《Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE》這兩篇文章請您務必抽時間讀一讀。
  • 微信小程序中如何使用WebSocket實現長連接(含完整源碼)
    (說明:本文完整源碼請從文末附件下載,52im.net/thread-1703-1-1.html)2、相關文章《新手入門貼:史上最全Web端即時通訊技術原理詳解》《Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE》《新手快速入門:WebSocket簡明教程》《WebSocket詳解(一):初步認識WebSocket技術》《WebSocket詳解(二
  • 微信不能承受之痛:B端即時通訊產品設計
    本文從北京鐵路局12.6事故出發,詳細分析了「消息」和「指令」的定義,引出了B端即時通訊工具的核心特徵,並介紹了B端即時通訊工具如何構建,最後列舉了市面上典型的產品案例。痛定思痛,希望將事故的教訓轉化為具體的行動;並祝願善良的人一生平安。
  • websocket項目 搭建node專題及常見問題 - CSDN
    之前項目裡做即時通信都是用的輪循,輪詢的效率低,非常浪費資源,後面好幾個項目都開始用的websocket配合koa和redis來實現,現在整理整理深入了解下整個即時通信實現的過程。前提:需要安裝的包koa 由 Express 幕後的原班人馬打造,使用起來比Node更優雅簡潔 https://koa.bootcss.com/koa-router 是路由導航,實際應用中可以認為node接口https://www.npmjs.com/package/koa-routerkoa-websocket koa的中間件對websocket的封裝 https://www.npmjs.com
  • 企業即時通訊是什麼?五大企業級即時通訊功能分析
    企業即時通訊:簡稱EIM,是適用於企業使用的員工溝通和聊天內容管理的服務,公司員工可以通過企業即時通訊軟體,進行日常工作的實時溝通、待辦、語音、文件互傳等。相對於個人即時通訊來說(像QQ),企業即時通訊更加強調安全、實用、穩定以及擴展性,並且可以根據企業在實際使用中的需求,做定製化開發。
  • WebSocket能幹些啥?
    所以就一個梗:支付寶偷偷調用你的相機給你拍照下面我們就來了解websocket協議:HTTP是單工的還是雙工的還是半雙工的先來區分三者的含義1.單工: 數據傳輸只允許在一個方向上的傳輸例如:websockethttp協議是什麼工作模式呢分版本,版本不同,工作模式不同1.http1.0:單工。因為是短連接,客戶端發起請求之後,服務端處理完請求並收到客戶端的響應後即斷開連接。
  • 阿里、騰訊、今日頭條都入局的即時通訊領域,為何一時炙手可熱?
    艾瑞《2016即時通訊雲服務報告》認為:即時通訊雲服務商是將即時通訊技術封裝成 SDK 供 App 開發者下載使用,並向開發者提供平臺環境、技術支持、UI 前端以及後期運維等服務,使 App 能夠快速獲得消息實時收發的能力,實現單聊、群聊等功能,滿足社交,客服、聊天室等場景需求。
  • 日本即時通訊巨頭LINE與韓國ICON合作組建區塊鏈企業Unchain
    金色財經 區塊鏈5月17日訊 估值16億美元的韓國最大跨鏈區塊鏈項目ICON宣布與日本即時通訊應用LINE成立一家名為「UnChain」的新公司,雙方將在去中心化應用領域裡展開合作。事實上,早在今年一月,即時通訊應用巨頭LINE就宣布要進軍全球加密貨幣市場,他們計劃推出一個加密貨幣交易平臺,並加速區塊鏈技術的研發力度。
  • Web前端應用十種常用技術
    隨著JS與XHTML的應用普及,越來越多的web界面應用技術出現在網站上,比如我們常見的日曆控制項,搜索下拉框等,這些web界面應用技術大大的豐富了網站的表現形式,本文將為您精心推薦十種最常見的web界面應用技術。Web應用程式的界面設計,其核心就是網頁設計 ,但它的重點主要是在功能方面。
  • 「最新乾貨教程」2020免費下載高權限web of science、PubMed文獻
    如何免費下載web of science、PubMed、Wiley等論文期刊,最新教程,請查收~ISI Web of Science 是全球最大、覆蓋學科最多的綜合性學術信息資源,收錄了自然科學、工程技術、生物醫學等各個研究領域最具影響力的超過
  • 構建端到端ML框架的經歷啟示錄
    為什麼需要端到端ML框架大多數人(Cortex貢獻者)都有devops和web開發的背景,他們習慣於將應用程式的不同層抽象成單一接口的框架。每個剛剛開始學習機器學習的人,都會感慨工具的脫節。但是試圖構建一個涵蓋多個用例的端到端框架,那你就錯了,尤其是特別是在只有少數貢獻者的情況下。web框架或許會給我們啟發,想想它們是什麼時候開始嶄露頭角的吧。Rails、Django和Symfony都是在2004年到2005年間發布的,它們都是web新MVC框架的一部分。
  • 即時配送是否會推動現代物流與供應鏈體系變革?
    線上與線下融合的新零售變革又推動了貨物由前置到倉向前置到店發展,為由店到客戶的端到端即時配送打下了基礎。目前,新零售業務持續爆發增長,即時配送與新零售前置到店的貨物對接,推動即時配送服務邊界擴張,這是即時配送快速發展的天時條件。
  • 仿微信的IM聊天時間顯示格式(含iOS/Android/Web實現)[圖文+源碼]
    學習交流:- 即時通訊/推送技術開發交流4群:101279154 [推薦]- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》(本文同步發布於:http://www.52im.net/thread-2371-1-1.html)2、
  • 小區突然斷網?竟是通訊公司前員工盜割光纜!
    如果有天晚上突然斷網...那一定是電信的問題!如果不是?那會是誰?2020年10月11日,顧路派出所接電信工作人員報警稱:本區一路口,通訊電纜被盜。經現場勘驗,共計550米電纜線被盜,涉案價值10萬元左右。
  • 雅虎將娛樂進行到底 即時通訊軟體增加遊戲功能
    雅虎有可能將在其即時通訊軟體中加進一些新功能,包括讓用戶一邊聊天一邊聽音樂以及管理即時通訊地址簿等。目前,該公司正在調查用戶對這些新功能的反應。  在過去一周裡,雅虎有選擇性地向瀏覽該公司網站的用戶進行了調查,詢問用戶對這些新功能的反應。   雅虎即時通訊軟體的新功能包括:遊戲、好友圖標、個性化圖像和隱身模式等。
  • Web前端和後端有什麼區別(上)
    三、web後端和前端是怎麼連接的? 1、Web伺服器(apache, tomcat等),網絡協議(http, socket等),瀏覽器(chrome, FF, IE等)。
  • 為什麼說基於TCP的移動端IM仍然需要心跳保活?
    1、前言 很多人認為,TCP協議自身先天就有KeepAlive機制,為何基於它的通訊連結,仍然需要在應用層實現額外的心跳保活?本文將從移動端IM實踐的角度告訴你,即使使用的是TCP協議,應用層的心跳保活仍舊必不可少。
  • 用Scala實現簡單的Web和API伺服器
    這篇指南將向你介紹如何利用Scala簡單的HTTP伺服器,來提供Web內容和API。本文還會介紹一個完整的例子,告訴你如何構建簡單的實時聊天網站,同時支持HTML網頁和JSON API端點。這篇文及章的目的是介紹怎樣用Scala實現簡單的HTTP伺服器,從而提供網頁服務,以響應API請求。
  • Web1.0與Web2.0和Web3.0的本質區別是什麼
    ,從只有靜態網頁的web1.0到用戶直接交互的web2.0,再到用戶自主控制數據的web3.0。經過十多年的發展,web2.0的已經極大豐富。而web3.0才剛剛露出尖尖角,它以區塊鏈和加密貨幣為重要基礎,引導網際網路走向個人控制數據所有權,並實現個人隱私。但向真正走向web3.0,並非坦途,web2.0經過十多年的發展,由全世界如此眾多的聰明人不斷改進才取得今日的成就,而web3.0要成為主流採用的網絡,所需的時間也不可能短。
  • 愛分析·中國智能通訊雲行業趨勢報告 - IT業界_CIO時代網 - CIO...
    智能通訊雲應用趨勢展望結語關於愛分析法律聲明1.智能通訊雲行業概覽我國通訊發展經歷了PC網際網路時代,2009年國家大規模部署3G移動通訊網絡,2014年大規模部署4G移動通訊網絡,在這兩次移動通訊基礎設施的迭代後,移動網際網路得到快速發展,商業模式與服務模式創新不斷,即時通訊及實時音視頻業務普及,帶來了移動網際網路的用戶結構變化