【融雲分析】 IM 即時通訊之鏈路保活
眾所周知,IM 即時通訊是一項對即時性要求非常高的技術,而保障訊息即時到達的首要條件就是鏈路存活。那麼在複雜的網路環境和國內安卓手機被深度定製化的條件下,如何保障鏈路存活呢?本文詳解了融雲安卓端 SDK 在基於 TCP 協議實現鏈路保活方面的探索和經驗。
IM 系統整體框架
如上圖所示,為了保障鏈路存活,一套成熟的 IM 系統一般會包含訊息鏈路和推送鏈路兩條長連線通道。當有新訊息到達時,訊息服務首先會判斷訊息鏈路是否存活,如果訊息鏈路處於存活狀態,訊息優先從訊息鏈路下發到客戶端,否則會被路由到推送伺服器,由推送鏈路下發。
綜上所述,鏈路保活涉及到訊息鏈路和推送鏈路兩條鏈路的保活策略。基於這兩條鏈路使用場景的不同,保活策略上除了心跳機制是相同的,其它保活策略各有不同。下面將詳細講解。
鏈路保活的必要性
基於 TCP 的 Socket 連線建立之後,如果不做任何處理,這個連線會長時間存在並且可用嗎?答案是否定的。原因有兩點:
一、預設 Socket 連線無法及時探測到鏈路的異常情況,即使將 Socket 的屬性引數 keepAlive 設定為 true 仍然無法及時獲取到鏈路存活狀態。這是因為 Socket 的連線狀態是由一個狀態機進行維護的,連線完畢後,雙方都會處於建立狀態。假如某臺伺服器因為某些原因導致負載超高,無法及時響應業務請求,這時 TCP 探測到的仍然是連線狀態,而實際上此鏈路已經不可用了。
二、國內運營商的 NAT 超時機制會把一定時間內沒有資料互動的連線斷開,這個時間可能只有幾分鐘,遠無法滿足我們的長連線需求。
通用保活機制 - 心跳機制
基於以上原因,要維持 Socket 連線長時間存活,就需要實現自己的保活機制。最通用的一種保活機制就是心跳機制。即客戶端每隔一段時間給伺服器傳送一個很小的資料包,根據能否收到伺服器的響應來判斷鏈路的可用性。為了節省流量,這個包一般非常小,甚至沒有內容。
那麼客戶端如何實現定時傳送心跳包呢?一般有兩種方式:
一種是透過 Java 裡的 Timer 來實現。最基本的步驟如下:
1、建立一個要執行的任務TimerTask。
2、建立一個Timer例項,透過Timer提供的schedule()方法,將 TimerTask 加入到定時器Timer 中,設定每隔一段時間執行 TimerTask , 在 TimerTask 裡傳送心跳包。這種方式實現起來較簡單,而且省電,不需要持有 WakeLock 。缺點也很明顯,長時間在後臺,程式被回收或者系統休眠後, Timer 機制隨之失效。
另外一種方式是利用安卓系統的定時工作管理員 AlarmManager 迴圈執行傳送心跳包的任務。這種方式不會因為系統休眠而失效,系統休眠後仍然可以透過 WakeLock 喚醒,執行心跳任務,因此相對 Timer 機制,這種方式比較費電,使用的時候一定要注意如下幾點:
首先根據需求合理使用 AlarmManager 的鬧鐘引數。鬧鐘各引數的區別參考下表:
其次 AlarmManager 提供了 cancel() 方法,在設定新的定時任務前,透過 cancel() 方法取消系統裡設定的同型別任務,避免設定冗餘任務。
最後,安卓從 6.0 版本引入了 Doze 模式,並提供了新的鬧鐘設定方法 setExactAndAllowWhileIdle(),透過該方法設定的鬧鐘時間,系統會智慧排程,將各個應用設定的事務統一在一次喚醒中處理,以達到省電的目的。推薦在安卓 6.0 以上系統中,優先使用該方法。
訊息鏈路保活機制
訊息鏈路作為收發訊息的主要通道,需要最大程度保障鏈路的可用性。在鏈路不可用或者異常斷開時,能及時探測並啟動重連等保障機制。基於以上特性,訊息鏈路除了前面所說的心跳機制外,還另外維護了兩套鏈路最佳化機制:複合連線機制和重連機制。
複合連線機制的基本步驟如下:
1. 客戶端連線導航伺服器,導航伺服器會下發應用對應的配置資訊,其中包括連線伺服器的地址列表。
2. 客戶端從第一個伺服器地址嘗試連線,並啟動超時機制,如果連線失敗或沒有及時收到服務響應, 則繼續嘗試連線下一個直到成功連線,將成功連線的地址儲存到本地,作為最優地址,後面連線時優先使用此地址。透過這種機制,能保障客戶端優先選用最優鏈路,縮短連線時間。
重連機制,則是指業務層在檢測到與伺服器的連線斷開後,嘗試 N 次重新連線伺服器,首次斷開 1 秒後會重新連線,如果仍然連線不成功,會在 2 秒後(重連間隔時間為上次重連間隔時間乘 2 )嘗試重新連線伺服器,以此類推當嘗試重連 N 次後,仍然連不上伺服器將不再嘗試重新連線,只有在網路情況發生變化或重新開啟應用時才會再次嘗試重連。
推送鏈路保活機制
推送鏈路作為訊息到達的補充手段,要求儘可能延長在後臺的存活時間。即使被殺後,仍然能被再次喚醒。iOS 手機有 APNS 來達到以上效果,但安卓的官方推送系統 FCM 在國內基本不可用。那在國內安卓系統上如何保障推送到達呢?首先我們們需要先了解下安卓系統上程式管理的兩大機制:
一種是 LMK 機制,英文是 Low Memory Killer, 基於 Linux 的記憶體管理機制衍生而來。主要是透過程式的 oom_adj 值來判定程式的重要程度,從而決定是否回收這些程式。oom_adj 的值越低,代表重要度越高,比如 native 程式,framework 層啟動的系統程式,優先順序一般都為負數。其次是前臺可見程式,系統也不會回收。然而可見程式退到後臺後, oom_adj 的值會立即升高,在系統定時清理時被殺。
另外一種機制是安卓原生的許可權管理機制(AppOps),各大廠家在此基礎上又進行了深度定製化,比如小米的安全中心,華為的手機管家等,都用來進行許可權管理。該許可權管理機制執行在安卓系統的框架層,上層各應用的程式如果想嘗試重新啟動,系統首先會去許可權管理中心檢查該程式有沒有自啟動許可權,如果有,才准予啟動。否則,從框架層直接限制系統的啟動。
基於以上兩種機制,推送鏈路的保活也可分為兩大類,
一 程式保活。它的思路是根據 LMK 機制提高程式優先順序,降低被殺的機率。主要有以下幾種方法:
監聽黑屏事件,啟動 1 畫素透明 Activity ,使應用程式轉為可視程式,降低被殺機率。在螢幕亮時,關閉該 Activity。
雙服務守護。A 服務以 startForeground() 形式啟動,傳送一個通知,B 服務同樣以 startForeground() 形式啟動,且傳送和 A 相同 ID 的通知,然後在 B 服務裡呼叫 stopForeground() 方法,取消通知。這樣 A 服務就會以前臺程式的形式存活,且不影響使用者感知。
根據檔案鎖互斥原理,監視 Java 程式存活狀態,若被殺,Linux 層成功持有檔案,則透過 exec() 命令,開啟一個純 Linux 的可執行檔案,開啟一個 Daemon 程式, 該程式因為從 Linux 層啟動,在安卓 5.0 之前,優先順序會比較高,不會被殺。在安卓 5.0 之後,該方式不再有效。
二 程式拉活的策略和安卓系統的 AppOps 機制有關,一般有如下幾種:
一、利用 Service 本身的 Sticky 屬性,在 Service 的 onStartCommand() 中返回START_STICKY,這樣當 Service 被殺掉後,系統會自動嘗試重啟。不過在國內定製化的系統上,這種方式能成功重啟的機率很低,需要使用者在許可權管理中心開啟自啟動等許可權,才能成功拉活。
二、也就是前面講過的心跳機制,不過這裡要求使用 AlarmManager 設定 ELAPSED_REALTIME_WAKEUP 屬性的鬧鐘,在系統休眠後,才會正常接受到心跳事件,從而將程式拉活。
三、透過監聽網路切換,使用者行為等事件,拉起程式。
四、應用間互相拉活。比如系統裡有好幾個應用整合了同一個 SDK , 那麼在使用者啟動其中某一個 App 的時候,SDK 會去掃描其它應用,把"兄弟姐妹" 拉活。這種方式對使用者體驗傷害非常大,會造成系統莫名其妙的耗電。
隨著安卓系統版本的迭代,對後臺程式的啟動管控越來越嚴。為了解決推送的問題,各手機廠家推出了自己的系統級推送服務。由廠家在 Framework 層統一維護一條推送通道,上層所有應用共同使用該推送鏈路,不需要再維護單獨程式。當前支援系統級推送的廠家有:小米、華為、魅族、vivo、OPPO,這種系統級別的推送省電,省記憶體,到達率高。應用可以根據手機型號的不同,優先使用廠家系統級別的推送,再配合自身的保活機制,最大程度保障推送的到達率。
整合第三方系統級推送之後,整個訊息的收發流程可以參考下圖:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900655/viewspace-2640400/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- iOS整合融雲SDK即時通訊整理iOS
- 重新認識融雲,「不止即時通訊」
- 融雲 x 川航: 為民航通訊安上“即時之翼”
- 區塊鏈IM社交系統開發,IM即時通訊平臺搭建app區塊鏈APP
- 淺談融雲即時通訊服務「日誌優化」優化
- Android 接入騰訊IM即時通訊(詳細圖文)Android
- SpringBoot整合開源IM框架MobileIMSDK,實現即時通訊IM聊天功能Spring Boot框架
- 基於 swoole擴充套件 的即時通訊 im套件
- 區塊鏈即時通訊系統開發,IM社交軟體開發app區塊鏈APP
- 區塊鏈IM聊天軟體開發,即時通訊系統搭建原始碼區塊鏈原始碼
- 「實戰」搭建完整的IM(即時通訊)應用(2)
- 「實戰」搭建完整的IM(即時通訊)應用(1)
- 區塊鏈社交軟體開發,IM即時通訊社交直播系統開發區塊鏈
- 區塊鏈IM社交直播軟體開發,即時通訊聊天系統開發區塊鏈
- react-native-tencent-im-ui 騰訊雲即時通訊 IM 服務的react-native,使用原生ui版本得sdkReactUI
- 企業社交直播軟體開發,區塊鏈IM即時通訊系統開發區塊鏈
- 區塊鏈即時通訊系統開發原始碼,IM社交軟體開發app區塊鏈原始碼APP
- 為自己搭建一個分散式 IM(即時通訊) 系統分散式
- 開源即時通訊IM框架 MobileIMSDK v6.3 釋出框架
- IM即時通訊聊天社交APP VX 聊天語音視訊系統APP
- 通過SignalR技術整合即時通訊(IM)在.NET中應用落地SignalR
- 揭祕得物客服IM全鏈路通訊過程
- 社交直播app開發,IM即時通訊開發,區塊鏈賦能實體經濟APP區塊鏈
- 即時通訊技術文集(第12期):網路保活、心跳機制等文章彙總 [共23篇]
- 即時通訊
- 如何使用Flutter封裝即時通訊IM框架開發外掛Flutter封裝框架
- 即時通訊IM,是時代進步的逆流?看看JNPF怎麼說
- 手淘千牛IM即時通訊-星巴克訊息開放實踐
- 魔方實時通訊im元件元件
- 融雲 IM 和 RTC 服務,「助攻」智慧物流等客戶打通鏈路、完善生態
- 移動辦公安全告急?融雲 x 海泰方圓,給即時通訊加把「安全鎖」
- 融雲參編,業界首個辦公即時通訊軟體安全標準重磅釋出!
- gochat - 純go實現的im即時通訊系統(支援水平擴充套件)Go套件
- 融雲網際網路通訊安全系列之端到端加密技術加密
- 即時通訊技術文集(第11期):IM通訊格式的選型及Protobuf專題 [共16篇]
- 即時通訊技術文集(第10期):IM通訊協議該選TCP還是UDP [共12篇]協議TCPUDP
- 【附下載】艾瑞《全球網際網路通訊雲研究報告》,融雲 IM 連續 8 年展現統治力
- im即時通訊原始碼/仿微信app原始碼+php即時通訊原始碼帶紅包+客服+禁言等系統php+uniapp開發原始碼APPPHP