本文由美團技術團隊分享,作者“健午、佳猛、陸凱、馮江”,原題“美團終端消息投遞服務Pike的演進之路”,有修訂。
1、引言
傳統意義上來說,實時消息推送通常都是IM即時通訊這類應用的技術范疇,隨著移動端互聯網的普及,人人擁有手機、隨時都是“在線”已屬常態,于是消息的實時觸達能力獲得了廣泛的需求,已經不再局限于IM即時通訊這類應用中。
對于美團這種移動端“入口”級應用來說,實時消息的推送能力已經深入整個APP的方方面面。目前美團應用中使用的推送技術,是一個被命名為Pike的一套易接入、高可靠、高性能的雙向消息實時投遞服務。
本文將首先從Pike的系統架構升級、工作模式升級、長穩保活機制升級等方面介紹2.0版本的技術演進,隨后介紹其在直播、游戲等新業務場景下的技術特性支持,并對整個系統升級過程中的技術實踐進行了總結,希望本文能給消息實時推送服務感興趣或從事相關工作的讀者以幫助和啟發。
(本文同步發布于:http://www.52im.net/thread-3662-1-1.html)
2、相關文章
實時消息推送技術文章參考:
- 《魅族2500萬長連接的實時消息推送架構的技術實踐分享》
- 《專訪魅族架構師:海量長連接的實時消息推送系統的心得體會》
- 《百萬在線的美拍直播彈幕系統的實時推送技術實踐之路》
- 《京東京麥商家開放平臺的消息推送架構演進之路》
- 《解密“達達-京東到家”的訂單即時派發技術原理和實踐》
- 《長連接網關技術專題(四):愛奇藝WebSocket實時推送網關技術實踐》
- 《喜馬拉雅億級用戶量的離線消息推送系統架構設計實踐》
- 《微信直播聊天室單房間1500萬在線的消息架構演進之路》
- 《百度直播的海量用戶實時消息系統架構演進實踐》
- 《技術干貨:從零開始,教你設計一個百萬級的消息推送系統》
美團技術團隊分享的其它文章:
- 《美團點評的移動端網絡優化實踐:大幅提升連接成功率、速度等》
- 《深度解密美團的分布式ID生成算法》
3、v1.0的前世今生
3.1 v1.0 的誕生背景
2015年,美團誕生了Shark終端網絡通道,為公司移動端提供長連代理加速服務。Shark通過網絡接入點的全球多地部署和保持長連來提升網絡請求的端到端成功率,降低端到端延時,從而提升用戶體驗。
Pike 1.0是基于Shark長連通道實現的應用內推送服務。由于底層傳輸基于Shark長連通道,使得Pike 1.0天生便具有了低延時、高可靠、防DNS劫持等優秀基因。目前Pike 1.0在美團內部的即時通訊聊天、營銷推送、狀態下發、配置同步等業務場景都有廣泛使用。
3.2 v1.0 的工作流程
Pike 1.0 移動端SDK會在每次長連接創建成功后:
- 1)使用APPID、設備唯一標識UnionID(美團唯一標識、點評唯一標識等)向服務器發起注冊;
- 2)在注冊成功之后業務服務端就可以通過Pike 1.0服務端SDK提供的接口,主動向設備的App推送消息;
- 3)服務端推送的消息通過長連接通道抵達客戶端,最后通過注冊的回調接口投遞給業務方。
整體工作流程參見下圖:
3.3 v1.0的優勢
Pike 1.0底層傳輸基于Shark長連通道。
所以Pike 1.0在以下幾個方面有不錯的表現:
- 1)防劫持:底層通道直接使用IP直連,省去DNS解析耗時的同時也避免了被DNS劫持的風險;
- 2)低延時:Shark長連接采用就近接入點長連接的方式,省去了傳統HTTP需要多次建連、握手的消耗,端到端數據傳輸延時相比HTTP大幅縮短;
- 3)安全高:Shark采用自定義二進制協議進行數據傳輸,進行了通道級別的TLS加密,防篡改,更安全;
- 4)體驗好:Pike 1.0與Shark共享服務集群,Shark長連通道在海外多地都部署了接入點,代理加速接入,網絡延時及成功率表現要優于常規請求。
PS:移動網絡下HTTP、DNS的優化文章,可以看看下面這幾篇:
- 《全面了解移動端DNS域名劫持等雜癥:原理、根源、HttpDNS解決方案等》
- 《美圖App的移動端DNS優化實踐:HTTPS請求耗時減小近半》
- 《百度APP移動端網絡深度優化實踐分享(一):DNS優化篇》
3.4 v1.0的技術痛點
Pike 1.0作為Shark的衍生產品固然有其閃光的地方,但是對Shark的強依賴所帶來的痛點更是讓開發人員叫苦不迭,主要痛點如下。
3.4.1)代碼結構耦合:
在客戶端SDK方面,Pike 1.0代碼與Shark代碼結構耦合,共用底層通道建連、數據加解密、二進制協議等邏輯。
Pike 1.0與Shark代碼結構示意圖:
耦合帶來的弊端一:代碼優化升級困難。針對一個SDK的變更經常需要更多地考慮對另一個SDK是否有負面影響,是否影響面可控,這就無端地增加了開發成本。
耦合帶來的弊端二:Shark與Pike 1.0的網絡配置環境共用,如上圖所示,通過DebugPanel對SharkTunnel進行網絡環境配置都會同時對Shark和Pike 1.0生效,但是業務方在使用的時候往往只關注其中的一個SDK,不同SDK之間的相互影響引入了很多客服問題,也給客服問題的排查帶來了較多干擾因素。
3.4.2)賬號體系混亂:
Pike 1.0在同一個App上只支持一種設備唯一標識UnionID,不同App上注冊使用的UnionID會有不同,例如美團使用美團唯一標識,點評則使用點評唯一標識。
假如一個業務只在一個App上使用的話Pike 1.0自然可以很好地工作,但是同一個業務有可能需要在多個App上同時使用(如下圖所示),如果業務方不對賬號體系進行兼容的話,美團App上使用點評唯一標識作為推送標識的業務將無法工作,點評App上使用美團唯一標識作為推送標識的的業務也會無法工作。
這就導致同一個業務在不同App上的推送標識ID邏輯會非常復雜,后端要同時維護多套賬號體系之間的映射,才能解決賬號體系混亂的問題。
Pike 1.0賬號體系不兼容示意圖:
3.4.3)推送連接不穩定:
Pike 1.0由于共用Shark的通道邏輯而缺乏推送場景專項優化,在檢測通道異常、斷連恢復等方面表現不夠優秀。在通道可用性上,Shark與Pike 1.0關注的SLA也有著很大的不同。
例如:Shark在長連接通道不可用的情況下,可以通過降級短連接來規避業務網絡請求持續失敗所帶來的成功率下降問題。但是對于Pike 1.0此時如果通道不能快速恢復的話就會造成業務消息投送失敗,將直接影響消息投遞成功率。所以Shark通道針對連接保活的公共邏輯并不能完美地應用在Pike 1.0業務場景上。
雖然Pike 1.0在Shark通道的基礎上進一步在協議層強化了心跳探測機制以提高通道可用性,但通道不能及時檢測異常還是時有發生。
此外:Pike 1.0內部使用的事件分發技術的可靠性還暫時沒能達到100%,零星地會上報一些異常斷連而導致推送不成功的客服問題。
綜上:針對推送連接不穩定專項優化的訴求也就不斷被提上日程。
3.5 v2.0的誕生
Pike 1.0現有的技術痛點在業務場景日益豐富的現狀下遭遇了諸多挑戰。
為求解決Pike 1.0現有在Android和iOS平臺運營上遇到的問題:
- 1)我們重新梳理產品架構與代碼實現;
- 2)與基礎技術部另一個服務于H5的消息投遞服務Pike Web進行產品融合。
進而推出全新的升級產品——Pike 2.0。
下圖展示了Pike 2.0的產品全景。針對Pike 1.0的現狀,Pike 2.0前后端都做了諸多優化,包括技術架構升級、集群獨立、協議擴展等。
其中在客戶端方面Pike 2.0提供了基于多語言實現服務于多平臺的SDK,在服務端方面Pike使用部署Java應用的分布式集群來提供服務。
Pike 2.0產品全景圖:
以下內容將主要從客戶端視角,詳細闡述Pike 2.0 客戶端SDK的技術方案設計,從原理上說明Pike 2.0帶來的技術優勢。
4、v2.0架構設計
針對上文提及的Pike 1.0代碼結構耦合的技術痛點,Pike 2.0進行了全新的架構升級,在代碼結構、環境配置、服務集群等方面上都與Shark保持產品隔離。
4.1 設計思想
經過接近一年的技術積累與沉淀,從Shark提煉的TunnelKit長連內核組件和TNTunnel通用通道組件已經趨于穩定,所以Pike 2.0選擇基于TunnelKit與TNTunnel來構建雙向消息通道服務。
具體優勢有:
- 1)Pike 2.0基于TunnelKit長連內核構建,能有效地復用現有長連接控制相關的功能,減少不必要的開發工作;
- 2)Pike 2.0能夠共享TNTunnel的相關通用特性,如Shark協議封裝、數據加解密等,后期維護成本較小;
- 3)Pike 2.0協議作為Shark協議的Payload傳輸,可以靈活定制自己特性相關的協議。
4.2 整體架構
客戶端架構演進圖:
整體架構如上圖所示,包括:
- 1)Pike接口層;
- 2)Pike通道層;
- 3)TNTunnel通道層;
- 4)TunnelKit長連內核層。
4.2.1)接口層:
Pike接口層旨在為主流前端技術棧中所有需要應用內消息服務的業務提供簡潔可靠的接口。
主要是:
- 1)Pike 2.0提供了 Android、iOS、MRN等公司主流技術棧的接入SDK,業務可以根據自己的需求靈活選擇;
- 2)Pike 2.0針對不同的消息QPS,設計了兩種不同Client(詳見下方);
- 3)Pike 2.0針對線上Pike 1.0系統提供了業務無感的遷移方案,業務方無需任何人力投入便可以從之前的Pike 1.0系統遷移至Pike 2.0系統來進行消息的收發。
針對第 2)點,我們是這樣設計的:
- 1)對于消息量超過50條每秒的業務,例如直播彈幕推送,我們推薦接入聚合消息Client;
- 2)對于消息量較小的其他業務,普通消息Client則可以滿足需求。
4.2.2)通道層:
Pike通道層是特性的實現層,所有Pike接口層的API調用都會通過線程調度轉變成封裝的Task在Pike通道層完成具體的操作,Pike通道層是單線程模型,最大程度規避掉了線程安全問題。
Pike特性如下:
- 1)斷線重連:鑒于長連接的不穩定特征,Pike 2.0通道通過斷線重連機制來使的業務方可以認為在網絡沒有發生故障的情況下是持續可用的;
- 2)業務鑒權:業務后端可以通過Pike 2.0通道對連接的監控來感知連接變更,同時對接入網絡的客戶端設備進行可用性判別;
- 3)別名機制:針對不同業務方對業務標識做了隔離,每個業務可以自定義標識ID,解決了Pike 1.0同一個App平臺不同業務必須強制使用相同標識ID的痛點;
- 4)上/下行消息:Pike 2.0是雙向通道服務,不僅支持Pike 1.0原有的消息推送能力,即服務端向客戶端發送下行消息;同時也支持客戶端主動發送消息,即客戶端向服務端發送上行消息。業務只要通過Pike 2.0系統便可以形成消息的閉環;
- 5)分組/聚合消息:Pike 2.0支持消息分組和消息聚合來滿足高QPS業務場景的使用。其中消息分組表示業務可以通過自定義標簽來對一組用戶進行消息廣播;消息聚合表示將短時間內井噴式的消息進行聚合下發以提高系統的吞吐量;
- 6)消息保序:Pike 2.0支持同一客戶端發送的上行消息有序投遞到固定的業務服務器;
- 7)獨立通道:Pike 2.0默認所有業務是使用一條共享的通道,針對業務量大或者對吞吐量有要求的業務可以自動切換獨享的通道來保證消息的投遞成功率和時延;
- 8)通道保活:Pike 2.0在連接保活的基礎上增加了通道巡檢,能夠在檢測到異常的情況下自動重啟通道,確保在要求長穩的環境下進一步提升通道可用性。
4.2.3)TNTunnel通道層:
TNTunnel通道層是封裝通用通道邏輯的功能層,主要涉及通道狀態管理、協議封裝、數據加解密等通用核心模塊,是將通用通道邏輯從原先Shark通道中提煉而成的獨立分層。
Pike協議雖然是構建在現有Shark協議之上的應用層協議,但是Pike通道已經和原先的Shark通道在邏輯上完全解耦。
- 一方面,Pike 2.0會最大限度地復用Shark協議已成熟的技術,但是又不依賴于原有的Shark邏輯;
- 另一面,后續涉及二進制協議、安全協議等協議方面的升級優化都可以同時服務于Pike 2.0。
4.2.4)TunnelKit長連內核層:
TunnelKit長連內核層主要功能是對接Socket來處理TCP或者UDP數據的發送與接收,管理各個連接的可用性等。
每條Pike 2.0通道在TunnelKit中都是維護一條連接的,通過心跳保活機制和連接管理來保證在網絡環境正常的情況下永遠有一條連接來承載Pike數據。
TunnelKit作為所有通道層的基礎,是決定上層長連接通道穩定性最重要的一層。
5、v2.0工作機制
在進行了全新推送架構升級的基礎上,Pike針對上文提及的Pike 1.0賬號體系混亂、推送連接不穩定的痛點重新設計并完善了工作機制。
其中,PikeClient作為Pike系統對接業務方的門戶,在整個Pike 2.0系統中起著至關重要的作用,本節將以PikeClient為切入點介紹其工作機制。
5.1 PikeClient生命周期
為了更好地維護Pike 2.0內部狀態,PikeClient使用狀態機來負責生命周期管理。
PikeClient生命周期圖:
如上圖所示,PikeClient生命周期主要包括如下幾個部分:
- 1)onStart:該狀態是業務方調用StartClient或者RestartClient之后進入的狀態,此時PikeClient已經正常啟動,之后Pike 2.0內部會發起業務鑒權并根據鑒權結果流轉到其他的狀態,如圖所示如果業務鑒權失敗則進入onStop狀態,如果業務鑒權成功則進入running狀態;
- 2)onStop:該狀態是業務方調用StopClient或者業務鑒權失敗之后進入的狀態,此時PikeClient已經停止工作,客戶端進入該狀態之后需要Restart才能重新使用;
- 3)running:該狀態是PikeClient長穩工作的狀態,此時Pike 2.0等待響應服務推送的下行消息或者隨時準備發送上行消息。作為雙向消息通道,Pike 2.0處理上下行消息的能力是完全并行的;
- 4)onReceive: 該狀態是PikeClient成功接收到下行消息之后進入的狀態,Pike 2.0將接收到的消息投遞給業務方之后重新進入running狀態等待下一次操作;
- 5)onSendSuccess/onSendFailure:該狀態是PikeClient發送上行消息之后進入的狀態,業務方可以通過監聽該狀態來獲取本次消息發送的結果。
通過基于狀態機的生命周期管理,既嚴格定義了PikeClient的工作流程,也可以準確監控其內部狀態,提高了PikeClient的可維護性。
5.2 PikeClient工作模式
針對Pike 1.0混亂的賬號體系痛點,Pike 2.0設計了全新的工作模式。
如下圖所示,Pike通過通道代理模塊提供共享通道和獨立通道兩種模式來滿足不通業務場景的需求。
5.2.1)共享通道模式:
共享通道模式是Pike 2.0基本的工作模式,新增的業務方在默認情況下都會使用該模式接入Pike 2.0。
在Pike 2.0中PikeClient與Pike通道服務是多對一的共享關系,每個業務方都會有自己的PikeClient,每個PikeClient都可以自定義消息推送標識ID而避免使用全局標識ID。業務后端可以精簡推送標識邏輯,避免同時維護多套賬號體系。
不同業務的PikeClient僅在接入層面做了業務隔離,在Pike 2.0通道中會由Pike通道服務完成統一的管理。這種多對一的共享關系使得所有Pike業務共享Pike 2.0通道特性,同時又可以針對每個業務的使用場景設置其特定的消息處理能力,每個接入Pike 2.0的業務方都只需要關注其自己的PikeClient即可。
5.2.2)獨立通道模式:
獨立通道模式是共享通道模式的拓展能力,Pike 2.0通過配置控制來決策是否切換至該模式。
Pike 2.0默認情況下所有業務方都是共享同一個Pike通道服務,然而鑒于業務場景的不同,每個業務對于消息吞吐量,消息時延等SLA指標的訴求也有差異,例如游戲業務對于消息時延過長的容忍性就比較差。針對特殊業務Pike 2.0提供了獨立通道切換的能力支持。
所有PikeClient都通過Pike通道代理模塊來對接Pike通道服務,Pike通道代理模塊可以通過開關配置來控制PikeClient與特定的Pike通道服務協同工作。通過運用代理模式,既保證了原有結構的完整性,在不需要調整Pike通道代碼邏輯的基礎上就能夠完成獨立通道能力支持;又可以擴展通道切換能力,有效地管理通道切換的流程,讓Pike 2.0通道最大化提供業務能力的同時避免資源浪費。
5.3 PikeClient保活機制
PikeClient的保活完全依賴Pike 2.0通道的保活,針對Pike 1.0推送連接不穩定的痛點,Pike 2.0通道在吸收Pike 1.0在保活機制方面沉淀的技術的基礎上繼續優化,最后設計出基于心跳探測、重連機制和通道巡檢的三重保活機制。
保活機制如下圖:
5.3.1)心跳探測:
心跳探測是一種檢查網絡連接狀態的常見手段,Pike長連接是TCP連接,而TCP是虛擬連接:如果實際物理鏈路中出現諸如異常網絡節點等因素導致連接出現異常,客戶端和服務端并不能及時感應到連接異常,這時就會出現連接的狀態處于ESTABLISHED狀態,但連接可能已死的現象,心跳探測就是為了解決這種網絡異常的技術方案。
PS:關于tcp協議為什么還需要心跳保活,可以詳讀這篇《為何基于TCP協議的移動端IM仍然需要心跳保活機制?》。
客戶端在心跳巡檢計時器設置的心跳周期到達時判斷是否存在上次心跳超時的異常,如果心跳超時則認為該連接已經不可用了,則會從連接池移除該連接并觸發下文的重連機制。
為了更快地發現通道異常,Pike 2.0對于心跳周期與心跳超時都是可配置的,針對不同App使用的場景可以靈活地設置。
而且在每次發送上行數據的時候都會及時檢測上次心跳是否超時,使得心跳探測結果不必等到下次心跳周期到達的時刻才知悉。
Pike 2.0并不是采用固定心跳頻率來發送心跳包,Pike 2.0會利用通道的上下行數據包來動態減少心跳包的發送次數。
此外,智能心跳也是Pike 2.0持續關注的話題,感興趣的讀讀下面這些:
- 《微信團隊原創分享:Android版微信后臺保活實戰分享(進程保活篇)》
- 《微信團隊原創分享:Android版微信后臺保活實戰分享(網絡保活篇)》
- 《移動端IM實踐:實現Android版微信的智能心跳機制》
- 《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》
- 《一文讀懂即時通訊應用中的網絡心跳包機制:作用、原理、實現思路等》
- 《融云技術分享:融云安卓端IM產品的網絡鏈路保活技術實踐》
- 《正確理解IM長連接的心跳及重連機制,并動手實現(有完整IM源碼)》
- 《一種Android端IM智能心跳算法的設計與實現探討(含樣例代碼)》
5.3.2)重連機制:
重連機制是Pike 2.0作為長連接通道最核心的特性,也是Pike 2.0連接穩定性建設最重要的一環。
客戶端會在發送消息、接收消息和心跳探測三個環節來決策是否需要觸發重連:
- 1)一方面,如果主動發現連接池中可用連接不足則自動啟動重連機制;
- 2)另一面,當現有可用連接關閉時也會自動觸發重連機制。
Pike 2.0在重連的過程中會采用斐波那契數列退避算法來發起建連請求直至建連成功:
- 1)一方面,Pike 2.0保證只要在網絡可用的情況下總能夠維持可用的長連接來服務于業務消息;
- 2)另方面,Pike 2.0在網絡持續不可用的情況下避免連續建連使得系統滿載。
有關斷線重連這方面的文章,可以系統的讀一讀下面這些:
- 《Web端即時通訊實踐干貨:如何讓你的WebSocket斷網重連更快速?》
- 《正確理解IM長連接的心跳及重連機制,并動手實現(有完整IM源碼)》
- 《手把手教你用Netty實現網絡通信程序的心跳機制、斷線重連機制》
PS:如果需要實踐性的代碼,也可讀一下開源工程MobileIMSDK ,它對于im的心跳和重連機制有完整的邏輯實現,可以借鑒參考。
5.3.3)通道巡檢:
通道巡檢是在心跳探測和重連機制的基礎上進一步提升Pike 2.0穩定性的有效機制。
客戶端會根據心跳周期設置一個全局的巡檢定時器,在每次定時器設置的時刻到達時,客戶端會觸發通道異常檢測邏輯,一旦發現異常都會嘗試重啟通道。
Pike 2.0首先會在觸發通道異常檢測的時候獲取當前通道狀態,如果通道當前沒有主動關閉但是通道處于不可用的狀態,Pike 2.0會強制執行一次自啟動。
此外,在通道巡檢的過程中,巡檢管理器會不斷收集消息收發過程中出現的超時異常,當超時異常次數連續累計超過配置的最大閾值時,Pike 2.0會認為當前通道可用性較低,需要強制關閉并執行一次自啟動。
6、v2.0新增的技術特性
Pike 2.0作為Pike 1.0的升級版,不只是為了解決Pike 1.0的技術痛點,通過新增特性以開拓新的應用場景也是Pike 2.0關注的點。
6.1 聚合消息
隨著公司內直播業務的興起,公司內部也有很多業務方使用Pike 1.0作為彈幕、評論、直播間控制信令等下行實時消息的傳輸通道。
但Pike 1.0基于早先的設計架構為彈幕、評論這種短時間需要處理海量消息的場景提供可靠服務的能力漸漸力不從心。
主要表現在QPS大幅增長時,消息投遞成功率降低、延時增加和系統性能開銷增長等方面。Pike通過引入聚合消息為直播場景中消息的投遞提出更加通用的解決方案。
6.1.1)設計思想:
直播場景中涉及的消息主要具備以下特點:
- 1)彈幕作為一種實時互動的載體,短時間內需處理大量的圖片、文本等信息,如果不做聚合會浪費大量的帶寬;
- 2)直播間相比普通推送場景,由于用戶已經進入直播間,用戶行為也相對統一可控,所以更需要一種群組消息來統一處理;
- 3)直播間對于不同類型的消息處理邏輯可以區分優先級,比如抽獎、控制信令是要求可靠性不能丟棄,而對于彈幕則可根據直播間熱度、服務承受能力適當丟棄。
聚合消息在設計上主要采用下述思想:
- 1)從時間維度對消息進行聚合,減少不必要的帶寬消耗;
- 2)采用消息分級策略,根據消息的類型設定不同的優先級,保證重要消息的可靠性;
- 3)抽象出類似直播間的聚合單元,統一管理加入聚合單元的用戶行為;
- 4)采用客戶端主動拉取的策略;
- 5)提供上行消息能力,提供更完整的消息流通路徑。
針對第 4)點:相比傳統的服務端推送策略,主動拉取是利用客戶端天然分布式的特點將用戶狀態保存在客戶端,服務端通過減少狀態維護進而可以留出更多的資源用于業務處理。
6.1.2)方案流程:
Pike 2.0針對每個聚合單元都使用環形隊列來維護消息列表,發送到該聚合單元的消息在經過優先級過濾之后都會插入隊列tail指針標示的位置,隨著該聚合單元內消息不斷增加最后達到最大隊列長度時,head指針會不斷移動來給tail指針騰出位置。聚合單元通過控制最大長度的環形隊列來避免消息短時間井噴式增長帶來的服務性能問題。
客戶端在主動拉取的時候都會攜帶上一次獲取到的消息處在環形隊列中的偏移量,這樣服務就會將偏移量標示的位置到tail指針標示的位置之間的消息進行聚合作為本次拉取的結果一次性返回給客戶端。不同客戶端各自維護自己的偏移量,以此來避免服務端對于客戶端的狀態維護。
客戶端與服務端的具體交互如下圖所示:客戶端在加入聚合單元之后主動拉取,如果本次拉取攜帶的偏移量能夠從服務的環形隊列中獲取到聚合消息,那么就將消息回調給業務之后馬上進行下一次拉取操作。如果本次攜帶的偏移量已經位于環形隊列tail指針的位置,那么服務端將不做任何響應,客戶端等待本次拉取超時之后開始下一次拉取操作,重復該流程直至客戶端離開該聚合單元。與此同時,業務服務端如果有消息需要推送,則通過RPC的方式發送給Pike服務端,消息處理模塊將執行消息分級策略過濾之后的有效消息插入環形隊列。
聚合消息交互流程圖:
6.2 消息保序
Pike 1.0在設計之初就只適用于消息推送的場景,而Pike 2.0在其基礎上演進為雙向消息投遞服務,即不僅支持下行的消息推送,還支持上行的消息投遞。Pike 2.0在上行的消息投遞方面進一步拓展了消息保序的功能。
這里的消息保序主要包含兩個層面的含義:
- 1)首先每一個業務客戶端發送的消息都最大程度地到達同一個業務服務器;
- 2)其次這些消息是按照客戶端發送的時序一致地到達該業務服務器。
6.2.1)粘性會話:
為了使每一個業務客戶端發送的消息都最大程度地到達同一個業務服務器,Pike 2.0引入了粘性會話的概念。
粘性會話指的是:同一客戶端連接上的消息固定轉發至某一特定的業務方機器處理,客戶端斷連重連后,保持新連接上的消息仍轉發至該業務機器。
粘性會話可以歸納為如下的流程:
- 1)首次業務登錄的時候Pike 2.0服務器會利用負載均衡算法選擇一臺業務服務器,并將該業務服務器的路由標識通過業務登錄結果通知客戶端并保存,之后如果通道狀態穩定的話所有的上行消息就都會投遞到該業務服務器;
- 2)如果期間通道狀態波動出現斷連的情況,Pike 2.0在發起重連之后會重新進行業務登錄,這一次業務登錄會將之前保存的路由標識重新上報給Pike 2.0服務器,這樣Pike 2.0服務器就會通過路由標識重新綁定該業務服務器;
- 3)如果路由標識指示的業務服務器已經停止提供服務,那么Pike 2.0服務器會重新通過負載均衡算法選擇新的一臺業務服務器,同時客戶端會獲取到新的路由標識,之后的邏輯重復該過程直至Pike 2.0客戶端退出。
6.2.2)時序一致性:
我們都知道TCP是有序的,那么在同一個TCP連接的前提下什么情況會出現客戶端發送的消息亂序到達業務服務器呢?
原因就是:Pike 2.0服務器從TCP中讀出消息之后將其投遞給業務服務器是通過RPC異步調用的。
為了解決這種問題:最簡單的方案當然是客戶端將消息隊列的發送窗口限定為1,每一條發送消息都在Pike 2.0服務器投遞給業務服務器之后才能收到ACK,這時再發送下一條消息。但是考慮到網絡傳輸在鏈路上的時延遠遠大于端上處理的時延,所以該方案的QPS被網絡傳輸設了瓶頸,假設一個RTT是200ms,那么該方案理論也只能達到5的QPS。
Pike 2.0為了提高上行消息保序投遞的QPS,采用服務端設置消息隊列緩存的方案。
如下圖所示:客戶端可以在發送窗口允許的范圍內一次性將多條消息發送出去,服務端把收到的消息都按順序緩存在消息隊列中,然后串行的通過RPC調用將這些緩存的消息依序投遞給業務服務器。
這種保序方案將QPS性能的瓶頸點從之前網絡傳輸在鏈路上的時延轉移到了RPC調用的時延上,而實際場景中一次RPC調用往往在幾個毫秒之間,遠遠小于網絡傳輸在鏈路上的時延,繼而顯著地提升了QPS。
消息時序一致性問題,在實時通信領域是個很熱門的技術點:
- 《零基礎IM開發入門(四):什么是IM系統的消息時序一致性?》
- 《如何保證IM實時消息的“時序性”與“一致性”?》
- 《一個低成本確保IM消息時序的方法探討》
- 《一套億級用戶的IM架構技術干貨(下篇):可靠性、有序性、弱網優化等》
7、v2.0的穩定性保障
7.1 監控體系
Pike 2.0依賴美團監控平臺Raptor完成監控體系建設,服務端和客戶端都建設了各自完善的指標監控。
Pike 2.0客戶端通過利用Raptor的端到端指標能力和自定義指標能力輸出了超過10+個監控指標來實時監控Pike系統,這些指標覆蓋通道建立、消息投遞、業務登錄、系統異常等多維度。
在實時指標監控的基礎上Pike 2.0針對不同指標配置了報警閾值,以推送消息為例,如果特定App的大盤數據在每分鐘的上下波動幅度超過10%,那么Raptor系統就會向Pike項目組成員推送告警信息。
基于所有Raptor監控指標,Pike 2.0提煉核心SLA指標如下:
Pike 2.0會定期輸出基于核心SLA指標的大盤數據報表,同時可以基于App、業務類型、網絡類型等多維度對數據進行篩選以滿足不同用戶對于指標數據的需求。
7.2 個案用戶追蹤
監控體系能從全局的角度反映推送系統穩定性,針對個案用戶,Pike管理平臺提供完整的鏈路追蹤信息。
每個Pike 2.0連接都由唯一標識Token來區分,通過該唯一標識Token在Pike管理平臺的“連接嗅探”模塊主動探測便能獲得對應連接上所有信令的交互流程。
如下圖所示:流程中明確標注了客戶端建立連接、發起鑒權、綁定別名等信令,點擊對應信令可以跳轉信令詳情進一步查看該信令所攜帶的信息,再結合SDK埋點在美團日志服務Logan的離線日志就可以快速發現并定位問題。
8、建設成果
截至2021年6月,Pike共接入業務200+個,日均消息總量約50億+,Pike 2.0消息到達率 >99.5%(相比Pike 1.0提升0.4%),Pike 2.0平均端到端延時<220ms(相比Pike 1.0減少約37%)。
部分應用案例:
- 1)直播場景消息服務方案:支持直播業務的直播互動功能,具備了支持同時在線百萬級別大型直播的能力;
- 2)消息推送、Feed流預加載等實時觸達方案:支持營銷類、控制類等業務消息實時推送,業務消息到達率最高提升10%,長連通道建聯耗時減少5%;
- 3)IoT設備接入方案:支持取餐柜業務IoT接入能力,幫助業務消息到達率從98.4%提升到99.6%;
- 4)小游戲場景消息投遞方案:支持美團小游戲場景通信能力,消息到達率達到99.8%以上,上行延時低至195ms。
9、未來展望
Pike實時消息推送服務在美團應用廣泛,目前主要集中在實時觸達、互動直播、移動同步等業務場景。隨著公司業務的快速發展,Pike對可用性、易用性、可擴展性提出了更高要求,希望提升各種業務場景下的網絡體驗。
因此未來Pike的規劃重點主要是:提供多端、多場景下的網絡通信方案,不斷完善協議生態,在各種應用場景下對抗復雜網絡。
具體就是:
- 1)拓展通用基礎能力:提升通道性能。通過優化保序方案,提供專用通道,優化傳輸協議等方式,進一步提升吞吐量和穩定性,降低推送時延;
- 2)建設物聯網的接入:提供IoT接入層方案。為公司內物聯網應用場景(單車、充電寶、取餐柜、智能頭盔、倉庫、門店設備等)提供統一的IoT接入層解決方案,支持多種接入協議(HTTP、MQTT、CoAP等),為業務提供安全可靠的設備連接通信能力;
- 3)優化弱網通信體驗:在移動端和IoT端基于美團自研MQUIC網絡協議庫,探索Pike over QUIC,在桌面端探索WebTransport技術,通過全面支持QUIC協議,提升弱網大包場景下的網絡性能,降低長尾分布的請求耗時。
附錄:更多實時消息推送技術文章
- 《iOS的推送服務APNs詳解:設計思路、技術原理及缺陷等》
- 《信鴿團隊原創:一起走過 iOS10 上消息推送(APNS)的坑》
- 《Android端消息推送總結:實現原理、心跳保活、遇到的問題等》
- 《掃盲貼:認識MQTT通信協議》
- 《一個基于MQTT通信協議的完整Android推送Demo》
- 《IBM技術經理訪談:MQTT協議的制定歷程、發展現狀等》
- 《求教android消息推送:GCM、XMPP、MQTT三種方案的優劣》
- 《移動端實時消息推送技術淺析》
- 《掃盲貼:淺談iOS和Android后臺實時消息推送的原理和區別》
- 《絕對干貨:基于Netty實現海量接入的推送服務技術要點》
- 《移動端IM實踐:谷歌消息推送服務(GCM)研究(來自微信)》
- 《為何微信、QQ這樣的IM工具不使用GCM服務推送消息?》
- 《極光推送系統大規模高并發架構的技術實踐分享》
- 《從HTTP到MQTT:一個基于位置服務的APP數據通信實踐概述》
- 《魅族2500萬長連接的實時消息推送架構的技術實踐分享》
- 《專訪魅族架構師:海量長連接的實時消息推送系統的心得體會》
- 《深入的聊聊Android消息推送這件小事》
- 《基于WebSocket實現Hybrid移動應用的消息推送實踐(含代碼示例)》
- 《一個基于長連接的安全可擴展的訂閱/推送服務實現思路》
- 《實踐分享:如何構建一套高可用的移動端消息推送系統?》
- 《Go語言構建千萬級在線的高并發消息推送系統實踐(來自360公司)》
- 《騰訊信鴿技術分享:百億級實時消息推送的實戰經驗》
- 《百萬在線的美拍直播彈幕系統的實時推送技術實踐之路》
- 《京東京麥商家開放平臺的消息推送架構演進之路》
- 《了解iOS消息推送一文就夠:史上最全iOS Push技術詳解》
- 《基于APNs最新HTTP/2接口實現iOS的高性能消息推送(服務端篇)》
- 《解密“達達-京東到家”的訂單即時派發技術原理和實踐》
- 《技術干貨:從零開始,教你設計一個百萬級的消息推送系統》
- 《長連接網關技術專題(四):愛奇藝WebSocket實時推送網關技術實踐》
- 《喜馬拉雅億級用戶量的離線消息推送系統架構設計實踐》
- 《直播系統聊天技術(三):微信直播聊天室單房間1500萬在線的消息架構演進之路》
- 《直播系統聊天技術(四):百度直播的海量用戶實時消息系統架構演進實踐》
- 《消息推送技術干貨:美團實時消息推送服務的技術演進之路》
- >> 更多同類文章 ……
本文已同步發布于“即時通訊技術圈”公眾號。

▲ 本文在公眾號上的鏈接是:點此進入。同步發布鏈接是:http://www.52im.net/thread-3662-1-1.html