對於移動APP來講,IM功能正變得愈來愈重要,它可以建立起人與人之間的鏈接。社交類產品中,用戶與用戶之間的溝通能夠產生出更好的用戶粘性。
在複雜的 Android 生態環境下,多種因素都會形成消息推送不能及時達到客戶端。另外,不穩定的移動網絡也給數據傳輸的速率和可靠性增長了障礙。
本文詳解了 網易雲信IM SDK在應對弱網環境、移動端硬件限制以及Android複雜的生態現狀時的探索與心得.如何實現不影響用戶體驗的後臺保活,改善的長鏈接加推送組合方案,以及在弱網環境大數據傳輸的優化實踐。
網易雲信即時通信推送保障及網絡優化詳解(三):如何在弱網環境下優化大數據傳輸算法
對於IM來講,及時的消息推送和較低的電量消耗也並不是不可兼得。在傳統上,每一個IM客戶端都會各自維護一條與服務器的長鏈接,本身的消息和信令都在這條長鏈接上傳遞,每一個APP也獨自去心跳,斷線重連等事情。緩存
這種模式比較簡單,不一樣的APP也是徹底隔離的,不會互相影響。但他的缺點也很是明顯:安全
首先是作了不少重複的事情,形成了流量和電量的無謂消耗;服務器
第二是要保證全部的進程都能在後臺運行很難。網絡
優化的方向也就很是明顯了,那就是共享鏈接,如今絕大部分推送SDK也是這麼作的。從這些APP裏面選出一個當前正在運行的,或者是被殺機率最低的APP做爲總代理,只由這個代理和服務器創建鏈接,一個手機上的全部其餘APP都經過這個代理中轉與服務器通訊。負載均衡
可是,IM有一個很基本的要求在這種模式下沒法獲得知足:安全。全部APP的消息都通過代理中轉,代理到服務器的鏈接是加密的,安全的,但到了代理這裏,消息都被解開了,所以代理理論上能夠看到其餘全部APP的來往消息。所以,這種共享長鏈接的方式並不適用於IM。大數據
雖然共享長鏈接方式不合適,但仍然提供了一個優化的思路。在此基礎上,有另外一個能夠脫敏共享鏈接的方式:安全長鏈接加推送鏈接模式。優化
每一個APP在使用和真正傳遞數據時,仍然獨立使用本身的安全長鏈接。而當APP退到後臺一段時間以後,則斷開長鏈接,而後每一個APP開啓一個推送代理,並選擇其中一個和網易雲信的推送服務器創建鏈接,以後當APP有新消息時,就經過這個推送鏈接傳遞。加密
APP能夠本身控制發出的推送消息的安全級別,能夠是包含說話人和消息內容,能夠只包含說話人,或者只是一條簡單的有新消息到達的提醒文案。推送到達後,若是是代理APP本身的消息,直接傳遞給代理APP便可。代理
若是是其餘APP消息,前面說到過,直接喚醒可能會失敗,並且會致使無謂的電量消耗,因此這裏並不直接將提醒傳遞給目標APP,而是由帶來發出一條通知欄提醒。等用戶去點擊通知欄提醒後,纔會把目標APP喚醒。
如今國內的ROM中,華爲和小米的系統原本是帶有推送系統,且開放給了第三方APP的。在這兩個系統上,使用系統的推送通道明顯會更加穩定,也更加節省資源。所以在MIUI上,從長鏈接到推送通道的切換流程仍然和前面的同樣,只是再也不使用本身的推送鏈接,而是將消息轉發到MIUI的推送服務器,而後轉給MIUI系統的推送代理,而後傳遞給網易雲信的APP。
華爲的推送系統流程也是同樣。不過如今華爲和MIUI在推送實現上有一些區別,例如MIUI的通知欄提醒是在本身的推送代理裏完成的,而華爲倒是將提醒通知交給APP本身去完成的,另外,他們的通知欄提醒的管理接口也有不少區別。
在APP沒有被禁用的狀況下,二者均可以收到推送,而若是APP已經被禁用了,MIUI的通知欄提醒方式還能夠將推送送達,而其餘的推送方式則不能送達了。
以上就是在保障消息推送方面所可以作的全部事情了。若是之後有更多的系統開放本身的推送系統也能夠選擇逐步接入,以提升推送到達即時性,減小資源消耗。不過相應的,也要承受不斷加入各類系統的推送SDK,增大發布包體積的缺點。
移動通訊網絡的三個特色:
第一個是慢,尤爲是2G,3G網絡,慢的使人髮指。
第二個是斷,手機跟着人不停的移動,網絡也不停的在切換,從wifi到移動網絡,從一個基站到另外一個基站,從有信號到沒信號,均可能致使網絡中斷。有些制式的網絡,接打電話也會致使數據網絡斷開。另外,移動基站還有NAT超時,到一個鏈接上長時間空閒後,基站就會默默的將鏈接斷開,沒有任何通知。
第三個是貴,這個就不用多說。
在網易雲信整個通訊系統中有3種類型的鏈接:TCP,UDP,HTTP。雖然說這三個並非同一層的協議,不過畢竟都在應用的更下層,所以這麼劃分也無妨。3種類型的協議對應了不一樣的業務應用。TCP主要是用戶長鏈接,也就是普通IM消息和信令的傳輸,UDP用於傳輸實時音視頻數據流,而HTTP則主要用在音頻,圖片等文件的上傳下載上。對於不一樣的業務,SDK優化的關注點會有一些不相同。
第一個是協議的選擇。前面說,長鏈接的使用量是最大,選擇一個合適的協議相當重要。若是是剛開始接觸IM開發,通常會選擇一些開源的協議,好比XMPP,SIP等。這是XMPP協議的一個請求樣例,能夠看到是一段XML格式的文本數據。
這是基於SIP的SIMPLE協議的一個請求樣例,能夠看到是一段相似HTTP協議的文本數據。這些協議的優點在於開源,有成熟的解決方案可使用,擴展性好,甚至還能夠和其餘系統互聯互通,協議的可讀性也很是好。可是在廣泛比較臃腫,冗餘字段不少,在昂貴的移動網絡裏面用起來會比較浪費。網易雲信採用的是私有的二進制協議,這是一個請求的數據樣例,這裏是把二進制數據轉爲了16進制顯示出來,每一個字節這裏顯示爲兩個字符。能夠看到二進制協議的特色在於徹底失去了可讀性,可是,卻帶來極高的表達效率,相對於文本協議,能夠節省很是多的數據流量。
另外一個例子是登陸的優化。因爲移動網絡常常斷開,因此登陸經常是心跳以外交互最多的協議了。使用量越大,優化就越有意義。通常而言,登陸會通過這麼幾步。
第一步是LBS。這裏的LBS不是常常說的基於地址位置的服務,在不一樣的廠商可能也有不一樣的叫法,反正做用都是獲取服務器的IP地址。像雲信這種須要提供全球服務的系統,在世界各地都要部署服務器,用戶登陸時,確定要選擇一臺最優的服務器接入服務。經過lbs,客戶端能夠獲取離本身最近,連通性最好的服務器鏈接機IP地址,服務器也能夠據此作負載均衡。
拿到服務器鏈接機IP後,客戶端就去鏈接該服務器。
鏈接成功,須要有一次握手。這個握手不是TCP的三次握手,而是爲了創建安全鏈接,同服務器協商加密算法和加密密鑰。
而後就發送登陸請求,這裏會帶上用戶認證信息,本機設備信息等數據。
登陸成功以後,就是同步數據,包括離線消息,用戶信息,羣組信息等。通常而言,這裏不會去作全量同步,而是採用基於時間戳的增量同步。
在移動網絡上,每一次交互都須要比較長的時間,同時,每一次網絡請求電量消耗也是很大的。因此,優化的方向就是儘可能減小交互次數,而方法則是合併請求,並行操做以及省略請求。
LBS和鏈接這兩個步驟是能夠並行完成的。若是前面已經獲取過LBS,這裏能夠有以前的緩存地址,若是沒有,能夠先連一個默認地址。
其次是握手和登陸也能夠並行操做。在握手包中,就能夠把加密後的登陸包直接帶上去了。若是是斷線重連,網易還能夠簡化登陸,直接帶上上一次登陸的會話ID,一來減小服務器鑑權壓力,二則能夠直接帶回在斷線期間是否有未讀消息等數據,若是沒有,則能直接將同步這一步省略掉。若是有,同步也能夠只作部分同步,只去拉去離線消息便可。等到APP切換到前臺,纔去同步其餘的信息。
經過這些優化,登陸時間能夠降爲原來的1/2到1/3,登陸的流量消耗也能夠節省30%左右。