posted @ 2021-12-08 17:23 Jack Jiang 閱讀(164) | 評論 (0) | 編輯 收藏
posted @ 2021-12-01 12:55 Jack Jiang 閱讀(187) | 評論 (0) | 編輯 收藏
posted @ 2021-11-27 13:00 Jack Jiang 閱讀(201) | 評論 (0) | 編輯 收藏
本文由阿里閑魚技術團隊逸昂分享,原題“消息鏈路優化之弱感知鏈路優化”,有修訂和改動,感謝作者的分享。
1、引言
閑魚的IM消息系統作為買家與賣家的溝通工具,增進理解、促進信任,對閑魚的商品成交有重要的價值,是提升用戶體驗最關鍵的環節。
然而,隨著業務體量的快速增長,當前這套消息系統正面臨著諸多急待解決的問題。
以下幾個問題典型最為典型:
- 1)在線消息的體驗提升;
- 2)離線推送的到達率;
- 3)消息玩法與消息底層系統的耦合過強。
經過評估,我們認為現階段離線推送的到達率問題最為關鍵,對用戶體驗影響較大。
本文將要分享的是閑魚IM消息在解決離線推送的到達率方面的技術實踐,內容包括問題分析和技術優化思路等,希望能帶給你啟發。

學習交流:
- 即時通訊/推送技術開發交流5群:215477170 [推薦]
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK
(本文已同步發布于:http://www.52im.net/thread-3748-1-1.html )
2、系列文章
本文是系列文章的第6篇,總目錄如下:
- 《阿里IM技術分享(一):企業級IM王者——釘釘在后端架構上的過人之處》
- 《阿里IM技術分享(二):閑魚IM基于Flutter的移動端跨端改造實踐》
- 《阿里IM技術分享(三):閑魚億級IM消息系統的架構演進之路》
- 《阿里IM技術分享(四):閑魚億級IM消息系統的可靠投遞優化實踐》
- 《阿里IM技術分享(五):閑魚億級IM消息系統的及時性優化實踐》
- 《阿里IM技術分享(六):閑魚億級IM消息系統的離線推送到達率優化》(* 本文)
3、通信鏈路類型的劃分
從數據通信鏈接的技術角度,我們根據閑魚客戶端是否在線,將整體消息鏈路大致分為強感知鏈路和弱感知鏈路。
強感知鏈路由以下子系統或模塊:
- 1)發送方客戶端;
- 2)idleapi-message(閑魚的消息網關);
- 3)heracles(閑魚的消息底層服務);
- 4)accs(阿里自研的長連接通道);
- 5)接收方客戶端組成。
整條鏈路的核心指標在于端到端延遲和消息到達率。
強感知鏈路中的雙方都是在線的,消息到達客戶端就可以保證接收方感知到。強感知鏈路的主要痛點在消息的端到端延遲。
弱感知鏈路與強感知鏈路的主要不同在于:弱感知鏈路的接收方是離線的,需要依賴離線推送這樣的方式送達。
因此弱感知鏈路的用戶感知度不強,其核心指標在于消息的到達率,而非延遲。
所以當前階段,優化弱感知鏈路的重點也就是提升離線消息的到達率。換句話說,提升離線消息到達率問題,也就是優化弱感知鏈路本身。
4、消息系統架構概覽
下圖一張整個IM消息系統的架構圖,感受下整體鏈路:

如上圖所示,各主要組件和子系統分工如下:
- 1)HSF是一個遠程服務框架,是dubbo的內部版本;
- 2)tair是阿里自研的分布式緩存框架,支持 memcached、Redis、LevelDB 等不同存儲引擎;
- 3)agoo是阿里的離線推送中臺,負責整合不同廠商的離線推送通道,向集團用戶提供一個統一的離線推送服務;
- 4)accs是阿里自研的長連接通道,為客戶端、服務端的實時雙向交互提供便利;
- 5)lindorm是阿里自研的NoSQL產品,與HBase有異曲同工之妙;
- 6)域環是閑魚消息優化性能的核心結構,用來存儲用戶最新的若干條消息。
強感知鏈路和弱感知鏈路在通道選擇上是不同的:
- 1)強感知鏈路使用accs這個在線通道;
- 2)弱感知鏈路使用agoo這個離線通道。
5、弱感知鏈路到底怎么定義
通俗了說,弱感知鏈路指的就是離線消息推送系統。
相比較于在線消息和端內推送(也就是上面說的強感知鏈路),離線推送難以確保被用戶感知到。
典型的情況包括:
- 1)未發送到用戶設備:即推送未送達用戶設備,這種情況可以從通道的返回分析;
- 2)發送到用戶設備但沒有展示到系統通知欄:閑魚曾遇到通道返回成功,但是用戶未看到推送的案例;
- 3)展示到通知欄,并被系統折疊:不同安卓廠商對推送的折疊策略不同,被折疊后,需用戶主動展開才能看到內容,觸達效果明顯變差;
- 4)展示到通知欄,并被用戶忽略:離線推送的點擊率相比于在線推送更低。
針對“1)未發送到用戶設備”,原因有:
- 1)離線通道的token失效;
- 2)參數錯誤;
- 3)用戶關閉應用通知;
- 4)用戶已卸載等。
針對“3)展示到通知欄,并被系統折疊”,原因有:
- 1)通知的點擊率;
- 2)應用在廠商處的權重;
- 3)推送的數量等。
針對“4)展示到通知欄,并被用戶忽略”,原因有:
- 1)用戶不愿意查看推送;
- 2)用戶看到了推送,但是對內容不感興趣;
- 3)用戶在忙別的事,無暇處理。
總之:以上這些離線消息推送場景,對于用戶來說感知度不高,我們也便稱之為弱感知鏈路。
6、弱感知鏈路的邏輯構成
我們的弱感知鏈路分為3部分,即:
- 1)系統;
- 2)通道;
- 3)用戶。
共包含了Hermes、agoo、廠商、設備、用戶、承接頁這幾個環節。具體如下圖所示。

從推送的產生到用戶最終進入APP,共分為如下幾個步驟:
- 步驟1:Hermes是閑魚的用戶觸達系統,負責人群管理、內容管理、時機把控,是整個弱感知鏈路的起點。;
- 步驟2:agoo是阿里內部承接離線推送的中臺,是閑魚離線推送能力的基礎;
- 步驟3:agoo實現離線推送依靠的是廠商的推送通道(如:蘋果的apns通道、Google的fcm通道、及國內各廠商的自建通道。;
- 步驟4:通過廠商的通道,推送最終出現在用戶的設備上,這是用戶能感知到推送的前提條件;
- 步驟5:如果用戶剛巧看到這條推送,推送的內容也很有趣,在用戶的主動點擊下會喚起APP,打開承接頁,進而給用戶展示個性化的商品。
經過以上5個步驟,至此弱感知鏈路就完成了使命。
7、弱感知鏈路面臨的具體問題
弱感知鏈路的核心問題在于:
- 1)推送的消息是否投遞給了用戶;
- 2)已投遞到的消息用戶是否有感知。
這對應推送的兩個階段:
- 1)推送消息是否已到達設備;
- 2)用戶是否查看推送并點擊。
其中:到達設備這個階段是最基礎的,也是本次優化的核心。
我們可以將每一步的消息處理量依次平鋪,展開為一張漏斗圖,從而直觀的查看鏈路的瓶頸。
漏斗圖斜率最大的地方是優化的重點,差異小的地方不需要優化:

通過分析以上漏斗圖,弱感知鏈路的優化重點在三個方面:
- 1)agoo受理率:是指我們發送推送請到的數量到可以通過agoo(阿里承接離線推送的中臺)轉發到廠商通道的數量之間的漏斗;
- 2)廠商受理率:是指agoo中臺受理的量到廠商返回成功的量之間的漏斗;
- 3)Push點擊率:也就通過以上通道最終已送到到用戶終端的消息,是否最終轉化為用戶的主動“點擊”。
有了優化方向,我們來看看優化手段吧。
8、我們的技術優化手段
跟隨推送的視角,順著鏈路看一下我們是如何進行優化的。
8.1 agoo受理率優化
用戶的推送,從 Hermes 站點搭乘“班車”,駛向下一站: agoo。
這是推送經歷的第一站。到站一看,傻眼了,只有不到一半的推送到站下車了。這是咋回事嘞?
這就要先說說 agoo 了,調用 agoo 有兩種方式:
- 1)指定設備和客戶端,agoo直接將推送投遞到相應的設備;
- 2)指定用戶和客戶端,agoo根據內部的轉換表,找到用戶對應的設備,再進行投遞。
我們的系統不保存用戶的設備信息。因此,是按照用戶來調用agoo的。
同時:由于沒有用戶的設備信息,并不知道用戶是 iOS 客戶端還是 Android 客戶端。工程側不得不向 iOS 和 Android 都發送一遍推送。雖然保證了到達,但是,一半的調用都是無效的。
為了解這個問題:我們使用了agoo的設備信息。將用戶轉換設備這一階段提前到了調用 agoo 之前,先明確用戶對應的設備,再指定設備調用 agoo,從而避免無效調用。

agoo調用方式優化后,立刻剔除了無效調用,agoo受理率有了明顯提升。
至此:我們總算能對 agoo 受理失敗的真正原因做一個高大上的分析了。
根據統計:推送被 agoo 拒絕的主要原因是——用戶關閉了通知權限。同時,我們對 agoo 調用數據的進一步分析發現——有部分用戶找不到對應的設備。 優化到此,我們猛然發現多了兩個問題。
那就繼續優化唄:
- 1)通知體驗優化,引導打開通知權限;
- 2)與agoo共建設備庫,解決設備轉換失敗的問題。
這兩個優化方向又是一片新天地,我們擇日再聊。
8.2 廠商推送通道受理率優化
推送到達 agoo ,分機型搭乘廠商“專列”,駛向下一站:用戶設備。
這是推送經歷的第二站。出站查票,發現竟然超員了。
于是乎:我們每天有大量推送因為超過廠商設定的限額被攔截。
為什么會這樣呢?
實際上:提供推送通道的廠商(沒錯,各手機廠商的自家推送通道良莠不齊),為了保證用戶體驗,會對每個應用能夠推送的消息總量進行限制。
對于廠商而言,這個限制會根據推送的類型和應用的用戶規模設定——推送主要分為產品類的推送和營銷類的推送。
廠商推送通道對于不同類型消息的限制是:
- 1)對于產品類推送,廠商會保證到達;
- 2)對于營銷類推送,廠商會進行額度限制;
- 3)未標記的推送,默認作為營銷類推送對待。
我們剛好沒有對推送進行標記,因此觸發了廠商的推送限制。
這對我們的用戶來說,會帶來困擾。閑魚的交易,很依賴買賣家之間的消息互動。這部分消息是需要確保到達的。
同樣:訂單類的消息、用戶的關注,也需要保證推送給用戶。
根據主流廠商的接口協議,我們將推送的消息分為以下幾類,并進行相應標記:
- 1)即時通訊消息;
- 2)訂單狀態變化;
- 3)用戶關注內容;
- 4)營銷消息這幾類。
同時,在業務上,我們也進行了推送的治理——將用戶關注度不高的消息,取消推送,避免打擾。
經過這些優化,因為超過廠商限額而被攔截的推送實現了清零。
8.3 Push點擊率優化
通過優化agoo受理率、廠商受理率,我們解決了推送到達量的瓶頸。但即使消息被最終送達,用戶到底點擊了沒有?這才是消息推送的根本意義所在。
于是,在日常的開發測試過程中,我們發現了推送的兩個體驗問題:
- 1)用戶點擊Push有開屏廣告;
- 2)營銷Push也有權限校驗,更換用戶登陸后無法點擊。
對于開屏廣告功能,我們增加了Push點擊跳過廣告的能力。
針對Push的權限校驗功能,閑魚根據場景做了細分:
- 1)涉及個人隱私的推送,保持權限校驗不變;
- 2)營銷類的推送,放開權限校驗。
以上是點擊體驗的優化,我們還需要考慮用戶的點擊意愿。
用戶點擊量與推送的曝光量、推送素材的有趣程度相關。推送的曝光量又和推送的到達量、推送的到達時機有關。
具體的優化手段是:
- 1)在推送內容上:我們需要優化的是推送的時機和相應的素材;
- 2)在推送時機上:算法會根據用戶的偏好和個性化行為數據,計算每個用戶的個性化推送時間,在用戶空閑的時間推送(避免在不合適的時間打擾用戶,同時也能提升用戶看到推送的可能性)。
- 3)在推送素材上:算法會根據素材的實時點擊反饋,對素材做實時賽馬。只發用戶感興趣的素材,提高用戶點擊意愿。
9、實際優化效果
通過以上我們的分析和技術優化手段,整體弱推送鏈路鏈路有了不錯的提升,離線消息的到達率相對提升了兩位數。
10、寫在最后
本篇主要和大家聊的是只是IM消息系統鏈路中的一環——弱感知鏈路的優化,落地到到具體的業務也就是離線消息送達率問題。
整體IM消息系統,還是一個比較復雜的領域。
我們在消息系統的發展過程中,面臨著如下問題:
- 1)如何進行消息的鏈路追蹤;
- 2)如何保證IM消息的快速到達(見《閑魚億級IM消息系統的及時性優化實踐》);
- 3)如何將消息的玩法和底層能力分離;
- 4)離線推送中如何通過用戶找到對應的設備。
這些問題,我們在以前的文章中有所分享,以后也會陸續分享更多,敬請期待。
附錄:相關資料
[1] Android P正式版即將到來:后臺應用保活、消息推送的真正噩夢
[2] 一套高可用、易伸縮、高并發的IM群聊、單聊架構方案設計實踐
[3] 一套億級用戶的IM架構技術干貨(上篇):整體架構、服務拆分等
[4] 一套億級用戶的IM架構技術干貨(下篇):可靠性、有序性、弱網優化等
[5] 從新手到專家:如何設計一套億級消息量的分布式IM系統
[6] 企業微信的IM架構設計揭秘:消息模型、萬人群、已讀回執、消息撤回等
[8] 移動端IM中大規模群消息的推送如何保證效率、實時性?
[10] 新手入門一篇就夠:從零開發移動端IM
[11] 移動端IM開發者必讀(一):通俗易懂,理解移動網絡的“弱”和“慢”
[12] 移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結
[13] IM消息送達保證機制實現(一):保證在線實時消息的可靠投遞
[14] IM消息送達保證機制實現(二):保證離線消息的可靠投遞
[16] 零基礎IM開發入門(二):什么是IM系統的實時性?
[17] 零基礎IM開發入門(三):什么是IM系統的可靠性?
[18] 零基礎IM開發入門(四):什么是IM系統的消息時序一致性?
本文已同步發布于“即時通訊技術圈”公眾號。
posted @ 2021-11-17 12:24 Jack Jiang 閱讀(201) | 評論 (0) | 編輯 收藏
posted @ 2021-11-10 15:18 Jack Jiang 閱讀(215) | 評論 (0) | 編輯 收藏
posted @ 2021-11-01 19:49 Jack Jiang 閱讀(154) | 評論 (0) | 編輯 收藏
posted @ 2021-10-26 14:41 Jack Jiang 閱讀(145) | 評論 (0) | 編輯 收藏
本文由阿里閑魚技術團隊有攸分享,原題“向消息延遲說bybye:閑魚消息及時到達方案”,有修訂和改動,感謝作者的分享。
1、引言
IM消息作為閑魚用戶重要的交易咨詢工具,核心目標有兩點:
- 1)第一是保證用戶的消息不丟失;
- 2)第二是保證用戶的消息及時送達接收方。
IM消息根據消息的接收方設備是否在線,分為離線和在線推送。數據顯示目前閑魚每天有超過一半以上的IM消息是走在線通道的,而在線消息的到達率、及時性是直接影響用戶體驗的。
本文將根據閑魚IM消息系統在消息及時性方面的優化實踐,詳細分析了IM在線通道面臨的各種技術問題,并通過相應的技術手段來優化從而保證用戶消息的及時到達。
PS:如果您對IM消息可靠性還沒有概念,建議先閱讀這篇入門文章《零基礎IM開發入門(二):什么是IM系統的實時性?》。

學習交流:
- 即時通訊/推送技術開發交流5群:215477170 [推薦]
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK
(本文同步發布于:http://www.52im.net/thread-3726-1-1.html)
2、系列文章
本文是系列文章的第5篇,總目錄如下:
- 《阿里IM技術分享(一):企業級IM王者——釘釘在后端架構上的過人之處》
- 《阿里IM技術分享(二):閑魚IM基于Flutter的移動端跨端改造實踐》
- 《阿里IM技術分享(三):閑魚億級IM消息系統的架構演進之路》
- 《阿里IM技術分享(四):閑魚億級IM消息系統的可靠投遞優化實踐》
- 《阿里IM技術分享(五):閑魚億級IM消息系統的及時性優化實踐》(* 本文)
3、當前面臨的問題
3.1 端內長連接中斷
在IM場景中,用戶與云端通信頻繁,且為了實現用戶的消息及時到達,往往采用云端下推消息的方式觸達用戶,所以用戶在線時設備與云端會維持一條TCP長連接通道,可以更輕量級的與服務端進行交互,現代IM即時通訊的下行消息都是通過長連下發的。
當前閑魚IM消息系統使用的是ACCS長連接,ACCS是淘寶無線提供的全雙工、低延時、高安全的通道服務。
但由于用戶設備網絡狀態的不確定性,可能會發生各種各樣的網絡異常情況導致ACCS長連接通道中斷。而長連接一旦意外中斷,就會導致用戶無法及時收到在線消息。

針對這個問題,我們需要盡可能及時的感知到長連中斷并嘗試重連。具體的優化思路會在本文后面的內容中分享。
3.2 下推的消息未達
感知長連中斷并重連只能在大多數時間保證長連接的有效性,但是在長連接無效或不穩定期間下推的消息客戶端可能根本收不到。
簡單說就是僅僅有重連機制無法保證下行消息必達,可能有以下場景導致下行消息失敗:
- 1)服務端發送下行消息時長連暢通,消息在傳輸路上通道斷掉,客戶端無法收到;
- 2)設備的在線狀態存在延遲,服務端下行消息時認為設備在線,實際上設備已經離線,無法收到;
- 3)客戶端收到了下行消息,但端上后續處理失敗(比如落庫失敗,消息沒有成功展示給用戶)。
我們通過數據埋點統計得出,ACCS長連接的下行成功率在97%左右。
ACCS長連接的下行成功率的統計方法如下:
ACCS下行成功率 = 通過ACCS成功下行且客戶端收到的消息量 / 服務端認為通過ACCS成功下行的消息量
有心急的同學就要問了,丟了3%的消息嗎?
并沒有!這3%的消息不會丟失,只是不保證及時觸達給用戶。
我們的消息同步模型是推拉結合模式,在用戶拉取消息時會拉取到設備當前位點與服務端最新位點的所有消息,ACCS下行失敗的消息會通過主動拉模式獲取到,但客戶端主動拉取消息的觸發時機有限。
當前客戶端主動拉取消息的觸發時機主要有以下幾個:
- 1)用戶冷啟動app,主動同步消息;
- 2)用戶主動下拉刷新;
- 3)app后臺切換前臺;
- 4)收到一條推送消息,客戶端發現新消息的位點跟本地最新的位點有gap,觸發同步。
可見:上述主動同步消息的觸發很大程度上依賴用戶行為或者有沒有收到新消息,難以保證消息及時到達。
如果是用戶高頻打開的IM軟件,這樣也不會有太大的問題。但是閑魚app的活躍度較低,有時候甚至依賴IM消息拉活,而且一條延遲的消息觸達可能導致用戶錯過一筆交易,閑魚消息不允許有這樣的延遲發生。
基于上述分析,我們先描述一個數據指標來反映現狀。
通過上面的描述可知:ACCS消息并不全都是推下來的,也可能是主動拉下來的。如果是推,必定可以及時到達;如果是拉,則受限于用戶行為。
拉的這部分消息,我們定義為ACCS消息補償到達,然后計算ACCS消息補償到達耗時,消息范圍限定為服務端ACCS成功下行但是客戶端通過主動拉取同步到的消息,以往的版本這個數據在60分鐘左右。
注意:這個數據并不是消息觸達到用戶的耗時,因為如果在線轉離線觸達,拉取到消息的時間取決于用戶行為(用戶何時打開了app),但這個數據也能大致反映在線消息的到達延遲狀況。
ACCS長連接的消息補償到達耗時的統計方法如下:
ACCS消息補償到達耗時 = 客戶端通過拉獲取到ACCS消息的時間 - 服務端ACCS下行時間
接下來本文將從長連接的重連和未達消息重發兩個方面詳細講述我們是如何優化在線通道穩定性的,從而優化并保證消息的及時到達。
4、優化手段1:增加長連接重連機制
4.1 長連接為什么會中斷?
有因必有果,我們先來分析下有哪些原因會導致連接中斷。
對于IM這種場景下來說,通常可能有以下原因:
- 1)用戶設備斷網;
- 2)設備發生了網絡切換;
- 3)設備處于弱網環境,網絡不穩定;
- 4)設備網絡正常,TCP連接由于NAT超時導致連接被運營商中斷。
對于APP來說,如果是用戶操作導致網絡狀態變化的情況,會有網絡狀態變化事件通知,這種情況可以監聽事件并主動嘗試重連。但現實中的大多數情況都是“意料之外”(正如上面列舉的這些斷網可能性一樣)。
那么既然“意料之外”的斷網無法預知,技術上可以如何有效的感知到各種異常狀況呢?
PS:如果要透徹理解斷網、弱網、TCP鏈接有效性,并不是本文能講的清楚的,可以參照下面的資料深入理解一下,值得好好學習。
關于TCP鏈接本身的有效性問題,可以讀以下兩篇:
關于移動網絡的復雜性問題,可以從以下幾篇入門的科普文章學習一下:
- 《IM開發者的零基礎通信技術入門(十一):為什么WiFi信號差?一文即懂!》
- 《IM開發者的零基礎通信技術入門(十二):上網卡頓?網絡掉線?一文即懂!》
- 《IM開發者的零基礎通信技術入門(十三):為什么手機信號差?一文即懂!》
- 《IM開發者的零基礎通信技術入門(十四):高鐵上無線上網有多難?一文即懂!》
關于移動弱網帶來的各種問題、優化方案等,可以通過以下幾篇系統學習一下:
- 《現代移動端網絡短連接的優化手段總結:請求速度、弱網適應、安全保障》
- 《移動端IM開發者必讀(一):通俗易懂,理解移動網絡的“弱”和“慢”》
- 《移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結》
- 《百度APP移動端網絡深度優化實踐分享(三):移動端弱網優化篇》
4.2 心跳檢測機制
像大多數鏈路保活場景一樣,IM這種場景下最有效的檢測手段就是心跳檢測(如果你對TCP鏈路保活還沒有什么概念,建議先讀《為何基于TCP協議的移動端IM仍然需要心跳保活機制?》)。
原理就是:客戶端通過定時發送心跳包,服務端收到心跳包后再反饋給客戶端,通過客戶端和服務端這一來一去的配合,就可以實現客戶服和服務端各自都能感知到連接是否中斷。
從及時性效果來看:心跳間隔越短越好,而頻繁的心跳檢測勢必會帶來用戶流量以及電量的損耗,所以我們的實現目標是如何盡可能少的心跳檢測而又盡量及時地感知到長連中斷的意外情況。
狀態機+消息心跳隊列:

在心跳協議設計上,要注意心跳包的核心目標是檢測長連通道是否暢通,客戶端主動上行心跳包且能收到服務端回包,就認為長連通道健康。所以心跳的上行消息以及回包的數據包應盡可能小。一般來說,通過協議頭標識心跳包及響應即可(這樣就能節省協議包大小)。
PS:關于心跳機制的入門文章可以詳讀《一文讀懂即時通訊應用中的網絡心跳包機制:作用、原理、實現思路等》。
4.3 心跳策略
心跳策略是實現我們上述目標的核心機制,本文僅簡單列舉幾種心跳策略。
比如以下這幾種:
- 1)短心跳檢測 初始狀態連續 ping 3次 收到 ACK 后,可以認為進入穩定狀態;
- 2)常規固定時長心跳(根據app狀態不同,頻率可調Mid+,Mid-, Long);
- 3)自適應心跳 根據設備網絡狀態變化自動適應的心跳間隔;
- 4)冗余心跳,app后臺切前臺,主動心跳一次。
關于心跳策略的詳細設計甚至可以單獨寫一篇文章,有興趣的同學可以閱讀以下推薦的文章繼續深入研究。
- 《微信團隊原創分享:Android版微信后臺保活實戰分享(網絡保活篇)》
- 《移動端IM實踐:實現Android版微信的智能心跳機制》
- 《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》
- 《融云技術分享:融云安卓端IM產品的網絡鏈路保活技術實踐》
- 《Web端即時通訊實踐干貨:如何讓你的WebSocket斷網重連更快速?》
- 《正確理解IM長連接的心跳及重連機制,并動手實現(有完整IM源碼)》
- 《一種Android端IM智能心跳算法的設計與實現探討(含樣例代碼)》
- 《手把手教你用Netty實現網絡通信程序的心跳機制、斷線重連機制》
5、優化手段2:消息ACK應答與重發機制
5.1 概述
為了解決上面的問題,我們同時也引入了消息ACK應答與重發機制。
整體思路是:客戶端在收到ACCS消息并處理成功后,給服務端回一個ACK應答包,服務端下發ACCS消息時將消息加入重試隊列,收到ACK應答包后更新消息到達狀態,并終止重試。
整體設計流程圖如下:

該方案的難點即重試處理器的實現設計,接下來我們將重點講述這部分的詳細設計。
5.2 重試隊列存儲設計
我們采用阿里云表格存儲TimeLine模型來存儲下行消息的到達狀態。Timeline 模型是針對消息數據場景所設計的數據模型,它能滿足消息數據場景對消息保序、海量消息存儲、實時同步的特殊需求,在IM、Feed流等消息場景應用廣泛。(關于TimeLine模型,這里有篇詳細的文章可以學習一下《現代IM系統中聊天消息的同步和存儲方案探討》)
我們給每個用戶設備定義一個TimeLine,timeline-id定義為userId_deviceId,sequenceId自定義為消息位點。
存儲結構如下:

每通過ACCS成功下行一條消息,則插入到接收用戶設備的TimeLine中,收到ACK后根據消息id更新消息到達狀態。
同時由于重試動作只發生在下行消息后較短的一段時間內,所以我們設置一個比較短的全局過期時間即可,避免數據膨脹。
5.3 延遲重試設計

如上圖所示:
- 1)每通過ACCS下發一條消息,先插入到Timeline中,初始狀態為未達,然后生產一條延遲N秒的延遲消息;
- 2)每次消費到延遲消息后,讀取tablestore中該消息的到達狀態,如到達則終止延遲,否則繼續;
- 3)每次重試先判斷設備是否在線,如果設備不在線,轉發離線通道并終止重試,如果設備在線,則重推未到達的消息,并再次延遲N秒消費;
- 4)每條消息的重試生命周期中用的同一條延遲消息,最多重試消費M次,超過次數不再重試并打日志埋點(后續可以監控這種情況并基于這個數據進行優化)。
5.4 延遲重發策略
延遲重發策略是指在重發流程中,如何選擇合適的延遲時間來使得重發的效率最高。
不同用戶在不同時間、地點所處的網絡環境差別較大,網絡恢復到穩定態所需要的時間也有差異,需要選用合適的延遲策略來保證重發效率。
最優的延遲策略的目標是在最短的時間內,使用最少的重發次數將消息投遞成功。以下是幾種可選的方案。
5.4.1)固定延遲時間:
要想找到最優的延遲策略,必須從數據中通過分析得到答案,天馬行空的想象往往離實際相差甚遠。
我們先采用固定的延遲時間(10s)最大重試6次來分析一波數據:

通過這組數據可以看到:有約85%的消息在40s內重發可以投遞成功,還有12%的消息在達到最大重試次數后依舊沒有收到ACK。在4次重試之后,第5次成功只有2.03%,第6次只有0.92%,繼續重發的收益已經變得很低。
6次以后還有部分消息沒有收到ACK,這部分消息如果用固定延遲時間策略,性價比很低,頻繁重發浪費系統資源,我們需要繼續改進策略。
5.4.2)固定延遲+固定步長遞增:
考慮到部分用戶的網絡短時間無法恢復,頻繁的短間隔重發價值不大,我們采用4次固定短間隔延遲N秒后,每次延遲時間都是上一次延遲時間遞增固定步長M秒的策略。直到收到ACK、用戶設備離線或者達到了最大延遲時間MAX(N)。
這種策略一定程度上可以解決固定延遲時間重發策略的問題,但如果用戶短時間網絡無法恢復,每次重發都要重新遞增,也不是一種最優解。
5.4.3)自適應延遲:
設計流程圖:

如上圖:我們最終衍生出了自適應延遲策略。
自適應延遲是指:根據用戶的網絡狀況,采取自動調整的延遲時間,以期望達到最高的重發效率。
具體是:新消息先通過4次固定N秒的短延遲來探測設備的網絡狀況,一旦網絡恢復,我們將設備的N值清空(設備N值是指根據上幾次重發經驗,當前設備網絡能回復ACK所需要的最短時間,默認情況該值為空,代表用戶設備網絡正常)。4次重發后依舊收不到ACK,我們嘗試讀取設備N值,如果為空,則取初始值,以后每次延遲都遞增固定步長M,并在重發后更新當前設備的N值,直到消息收到ACK或者達到了最大延遲時間MAX(N)。
5.5 新老版本兼容性
需要注意的是老版本的app是不會回ACK的,如果下發給老版本設備的消息也加入重試隊列,那此類消息將一直重試到最大次數才會終止,無端消耗資源。
所以我們設計在ACCS長連建立之后,客戶端主動上行一條設備信息,其中包含app的版本號,服務端存儲一定時間,在將消息加入重試隊列之前,先校驗接收者設備app的版本號,符合要求再加入重試隊列。
6、 最終優化后的效果
消息重連重發方案上線后,我們上面定義的指標 ACCS補償到達時間 從60分鐘大幅降低至15分鐘,降幅達75%。
從而印證了我們的技術分析,同時用戶有關消息延遲的輿情反饋大幅下降,可見消息重發機制對保證用戶消息及時到達成效顯著。
7、未來展望
消息在線通道的穩定性優化至此已告一段落,未來我們將繼續優化閑魚消息的使用體驗,包括基礎功能的完善以及基礎體驗的提升。
基礎功能方面:我們在近期的版本中已經支持了消息撤回、草稿功能,后續將逐步支持發送定位,會話分組、備注,消息搜索等功能。
基礎體驗方面:我們對消息的UI樣式做了優化升級,并優化了app消息tab頁的cpu及內存使用,后續將繼續從流量、電量、性能方面繼續優化消息的使用體驗。
附錄:參考資料
[1] 為何基于TCP協議的移動端IM仍然需要心跳保活機制?
[2] 不為人知的網絡編程(十二):徹底搞懂TCP協議層的KeepAlive保活機制
[4] 現代移動端網絡短連接的優化手段總結:請求速度、弱網適應、安全保障
[5] 移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結
[6] IM開發者的零基礎通信技術入門(十二):上網卡頓?網絡掉線?一文即懂!
[7] IM開發者的零基礎通信技術入門(十三):為什么手機信號差?一文即懂!
[8] 移動端IM實踐:實現Android版微信的智能心跳機制
[9] 融云技術分享:融云安卓端IM產品的網絡鏈路保活技術實踐
[10] Web端即時通訊實踐干貨:如何讓你的WebSocket斷網重連更快速?
本文已同步發布于“即時通訊技術圈”公眾號。
posted @ 2021-10-19 23:05 Jack Jiang 閱讀(257) | 評論 (0) | 編輯 收藏
posted @ 2021-10-11 14:35 Jack Jiang 閱讀(172) | 評論 (0) | 編輯 收藏
posted @ 2021-09-26 14:47 Jack Jiang 閱讀(221) | 評論 (0) | 編輯 收藏