1. 程式人生 > >國內APP訊息推送機制以及微信訊息延遲問題剖析

國內APP訊息推送機制以及微信訊息延遲問題剖析

轉自:https://club.huawei.com/thread-15878044-1-1.html

一、前言
隨著安卓手機以及QQ/微信/支付寶/滴滴出行/美圖外賣等一大批行動通訊/移動消費應用的日益普及,我們無時無刻不在享受著這些移動產品帶來的便利;但同時也會遇到一些困擾,比如QQ/微信/支付寶訊息延遲、微信/支付寶收款無語音播報、滴滴出行/美圖外賣商家版在後臺不能及時接單等問題,這些問題歸根到底還是Android應用訊息推送服務體驗差。
移動網際網路時代,訊息推送是移動應用的一項重要功能,今天我們來聊聊聊APP訊息推送機制,順帶著為大家解決微信訊息延遲問題。

二、國內APP訊息推送機制
目前中國安卓系統生態環境尚不成熟,裝置碎片化現象嚴重,導致不同應用與作業系統在適配性方面產生了一系列問題,訊息推送服務也會遇到各種障礙。

雖然在安卓手機上谷歌有推出GCM服務,由於GCM需要google service支援,在國內基本不能用。那麼,Android系統上的應用又是如何在沒有使用GCM服務的情況下把訊息推送給我們的呢?有如下三種方式:
1、使用第三方推送SDK
這是谷歌服務在國內執行情況不佳的產物,國內有多家第三方推送服務比如騰訊信鴿,百度,極光,個推,小米等,需要APP接入SDK,但是第三方推送服務可能會被系統殺掉,所以不同手機系統中不同第三方推送的訊息到達率/及時率參差不齊。
2、接入廠商統一推送
為了優化訊息推送成功率,降低電量和流量消耗,很多手機廠商也開始為開發者提供系統級推送服務,比如EMUI系統的華為推送、MIUI系統的小米推送、Flyme系統的魅族推送等,部分開發者為了提升訊息及時性會選擇整合主流的幾家推送,根據裝置進行區分,小米裝置使用小米推送、華為裝置使用華為推送、其他裝置使用第三方推送。

3、開發團隊自研發推送功能
開發團隊自研發推送功能需要投入開發成本、伺服器/頻寬成本,以及後期維護成本,而且推送效率並不一定比第三方高,大部分開發團隊會選擇介入第三方推送。
當前像微信這種超級應用,毋庸置疑肯定會選擇自研發。接下來,我們看下微信的訊息推送機制。

三、微信訊息推送機制
在Android下,不管是GCM還是微信,都是通過TCP長連線來進行推送訊息的,TCP長連線存活,訊息Push就及時。
所以,微信想要做到訊息及時推送,不止微信客戶端要後臺保活,TCP長連線也要保活。
1、如何保活TCP長連線
1)網路狀態變化時及時重連

網路狀態發生變化比如手機網路和WIFI網路切換、網路斷開和連上時,TCP長連線變為無效連線,所以微信會監聽網路狀態變化事件,及時重建長連線。

2)及時發心跳包防止NAT超時
因為IP v4的IP(即公網IP)有限,無法滿足人類使用(中國人用都不夠),所以運營商分配給手機終端的IP是運營商內網的IP,手機要連線Internet,就需要通過運營商的閘道器做一個網路地址轉換(NAT)。簡單的說運營商的閘道器需要維護一個外網IP、埠到內網IP、埠的對應關係,以確保內網的手機可以跟Internet的伺服器通訊。
大部分網路運營商在鏈路一段時間(幾分鐘或者十幾分鍾)沒有資料通訊時,會淘汰NAT表中的對應項(即NAT超時),從而內、外網IP之間再無法對應,造成TCP長連線無效。說到這裡,可能大家都想到了防止NAT超時的方法:客戶端間隔一定時間傳送一個心跳包給伺服器,及時重新整理NAT表,並告知伺服器客戶端當前的狀態;所以心跳包的主要作用是防止NAT超時,其次是探測連線是否斷開。
2、微信智慧心跳方案
為了保證微信收訊息及時性的體驗,當微信處於前臺活躍狀態時,會使用固定心跳;當微信進入後臺(或者前臺滅屏)時,微信會使用智慧心跳。
智慧心跳實際上就是先用幾次最小心跳維持長連結,然後動態的探測到最大的NAT超時時間,再選定合適的心跳間隔區間去傳送心跳包,同時在網路狀況發生變化的時候能夠動態的調整心跳間隔時間。
如果心跳間隔不合適,例如心跳間隔過短,那麼可能導致頻繁的喚醒手機發送心跳包,增加耗電;心跳間隔過長,可能導致這條TCP連線已經無效但是無法及時的檢測到,只能等待下一個心跳包傳送的時候才能感知到,所以會導致訊息接收延遲。
所以探測到一個合適的心跳間隔是非常重要的,把耗電和訊息接收及時性綜合折中來取得一個最佳的體驗,這個也是微信使用智慧心跳的原因。

四、微信延遲問題原因揭祕
上文有提到,微信想要做到訊息及時推送,不止微信客戶端要後臺保活,TCP長連線也要保活(及時傳送心跳),當然保持網路始終連線是前提條件。
原因1:鎖屏斷網
各大廠商均為使用者提供了"休眠狀態下是否保持網路連線"的開關,如果對微信訊息及時性要求高的同學,可以選擇"始終"。
以華為EMUI5.X系統為例,設定路徑為:
1)進入手機設定>WLAN>配置>在休眠狀態下保持WLAN連線,選擇始終;
2)進入手機設定>更多>行動網路>始終連線資料業務,開啟開關;

不過我發現,現在華為最新EMUI8.X系統上,即使不選擇“始終”,微信也可以及時收到訊息,應該是華為意識到微信訊息的重要性,對微信加了白名單。
原因2:運營商NAT超時時間較短
根據微信官方文件介紹,最小心跳為4.5min,但是國內有些地區有些運營商設定的NAT超時時間比較短(小於4.5min)。在這種網路下,如果是滅屏狀態,微信的TCP長連線基本上每隔幾分鐘就會斷開,直到重連後才可以收到訊息,加上目前各大廠商的省電策略,本身應用在後臺就非常不活躍,可能無法及時重連,這個就導致微信延遲概率更高、延遲時間更久。
這種網路很容易識別,如果你在4G網路下/其他運營商WiFi下不會延遲,只在特定網路下比如家裡的WiFi下高概率延遲,並且多個系列的安卓機都會延遲,那麼很可能是因為你使用網路的NAT超時時間比較短。
針對這類網路,曾經在貼吧見過網友給過一個解決辦法:打電話給運營商客服,要求把寬頻帳號加到外網。不過很多網友質疑可行性,然後樓主說是找在電信的朋友給加的。這個操作雖然理論上可以解決延遲問題,但是的確沒有可行性......
所以,遇到這種網路,如果不想換網路,但是又希望微信訊息及時接收的話,只能祈禱微信縮短最小心跳間隔,並且手機廠商不進行管控(所以我說了一堆廢話......)。

原因3:後臺清理微信
待機時長是使用者挑選機型時首要考慮的一個因素,手機發熱耗電快也是使用者吐槽非常多的一個問題。所以電池大小、充電速度、系統省電策略也是谷歌包括各大廠商在不斷改進(有可能越改越瞎)的事情。
當應用進入後臺或者系統滅屏時,能殺的全都殺掉:不在使用者保護名單裡,殺!高耗電應用,殺!不聽話應用,殺!
如果對微信訊息及時性要求高的同學,最好把微信加入清理白名單。
以華為EMUI5.X系統為例,設定路徑為:手機管家>剩餘xx%>鎖屏清理應用,將微信設定成鎖屏後不清理;
不過微信現在作為超級應用,基本沒有廠商敢在後臺殺微信的了,而且基本都會將微信加入受保護白名單,想一鍵清理也清理不掉,只有停止執行微信才可以,估計也有部分使用者會覺得很鬧心。

原因4:谷歌省電策略
1)Android 5.0:JobSchedule(對齊喚醒機制)

在待機狀態下,如果系統和App沒有發出動作,安卓其實是很省電的。不過,安卓App頻頻喚醒後臺,令安卓耗電大增。App每次喚醒裝置1到2秒,待機時間就會減少2分鐘。這並不僅僅指的是點亮螢幕,還有系統在處理應用的後臺任務。
谷歌在Android 5.0上提出API JobScheduler,系統可以批處理一些應用喚醒要求,減少電量消耗,也叫做對齊喚醒機制。
當然,谷歌的這個對齊喚醒機制需要應用主動呼叫,並且是針對不需要準時執行並且希望批量處理的任務,所以並不會影響微信訊息的及時推送。
2)Android 6.0:Doze模式、App Stanbdy
谷歌在Android 6.0上提出了兩個省電特性(Doze模式、App Stanbdy)以延長電池使用時間。
如果一個使用者斷開充電連線,滅屏不動手機一段時間之後,系統會嘗試延緩app後臺的CPU和網路活動(延緩應用的任務、同步和標準alarms,阻止應用訪問網路)減少電量的消耗。
當然應用可以通過適配來保證基本功能正常執行,使用者也可以選擇將應用加入白名單。
以華為EMUI8.X系統為例,設定路徑為:設定>應用和通知>應用管理>設定>特殊訪問許可權>忽略電池優化>微信,設定為允許。
原因5:廠商省電策略
各大廠商的省電策略相比谷歌省電策略,更加複雜粗暴,並且應用根本無法適配。目前瞭解到的廠商省電策略主要有如下幾種:
1)後臺斷網/後臺清理
上文提到,估計除了超級應用可以倖免於此了。並且有些APP即使加入白名單,依舊會被清理。
2)對齊喚醒機制
上文提到,谷歌在Android 5.0上提出的對齊喚醒機制並不會影響微信訊息的及時推送;但是廠商的對齊喚醒機制比較粗暴,會將所有應用在一定時間段內的多次喚醒合併成一次喚醒,減少系統被喚醒次數,增加待機時間。
而微信心跳就依靠這個定時器,在喚醒的時候傳送心跳給伺服器,如果被廠商對齊喚醒,心跳間隔就會比原本設定的長(比如從4.5min變成10min),那麼使用網路NAT超時時間<10min的這部分使用者就會出現NAT超時,微信訊息出現延遲。

而不同廠商的針對不同應用、在不同時間段的對齊時間可能還不一樣。
情況1:如果你白天不會延遲,只有晚上/半夜會延遲,那麼很可能是廠商在夜間做了省電策略,夜間對齊喚醒時間間隔比較久。
情況2”如果你在4G網路下/其他運營商WiFi下不會延遲,只在特定網路下比如家裡的WiFi下高概率延遲,並且其他系列手機均不會延遲,那麼很可能是因為你使用的這款機型的對齊喚醒時間間隔比較久(當然前提是手機上所有開關都設定好)。

手機廠商的這種做法,雖然為使用者節省了功耗,但是卻沒有給使用者足夠的選擇權,因為有些使用者相比節省功耗優先會選擇訊息及時性。
值得鼓勵的是華為EMUI8.X系統在近期更新的版本上給了使用者選擇權,當用戶選擇允許後臺活動後,不再對微信做對齊喚醒等管控。設定路徑為:
在設定>電池>啟動管理,找到微信,關閉"自動管理",開啟"手動管理"的三個開關"允許自啟動""允許關聯啟動""允許後臺活動"。
不過當前已經支援的版本並不多,只看到了P20系列 B108版本、Mate10系列 B129sp03版本。不過各位使用華為手機的朋友還是可以期待下,畢竟旗艦產品已經帶了,其他產品肯定也會陸續帶上~


五、微信訊息延遲問題-華為手機相關開關彙總
由於本人使用華為機比較多,針對華為手機統一整理了相關開關,其他廠商機型可以自行百度。
場景1:如果開啟微信沒有地球介面,說明微信在後臺沒有被殺,你需要進行如下設定:
如果是EMUI8.X產品:

1.允許微信後臺活動可以通過設定允許微信後臺活動,提升微信接收訊息及時性,操作步驟:
在設定>電池>啟動管理,找到微信,關閉“自動管理”,開啟"手動管理"的三個開關“允許自啟動”“允許關聯啟動”“允許後臺活動”。
注:當前已支援產品與版本有P20系列 B108版本、Mate10系列 B129sp03版本;其他EMUI8.X產品後續應該會陸續推送版本
2.將網路設定為始終連線
1)進入手機設定>無線和網路>WLAN>配置>在休眠狀態下保持WLAN連線,選擇始終;
2)進入手機設定>無線和網路>行動網路>高階>始終連線資料業務,開啟開關;
3)進入手機設定>無線和網路>行動網路>高階>WLAN/移動資料連線切換提示,選擇自動使用移動資料連線。
3.將微信設為忽略電池優化 設定>應用和通知>應用管理>設定>特殊訪問許可權>忽略電池優化>微信,設定為允許。
4.關閉省電模式 點選手機管家>剩餘xx%,關閉省電模式和超級省電的開關。
5.關閉省流量模式 手機管家>流量管理>省流量模式,關閉省流量模式;如果需要使用省流量模式,請開啟微信應用的開關,關閉後將無法在後臺接收新訊息。
6.開啟系統的通知功能 在設定>應用和通知>通知管理中找到微信,根據需要設定允許通知,以及通知方式(在狀態列、橫幅、鎖屏顯示通知)。
7.開啟微信應用內部的通知功能 在微信我>設定>新訊息提醒,開啟“接收新訊息通知”開關,並根據需要開啟或關閉“通知顯示訊息詳情”、“聲音”、“震動”。

如果是EMUI5.X產品:
1.將網路設定為始終連線
1)進入手機設定>WLAN>配置>在休眠狀態下保持WLAN連線,選擇始終;
2)進入手機設定>更多>行動網路>始終連線資料業務,開啟開關;
3)進入手機設定>更多>行動網路>WLAN/移動資料連線切換提示,選擇自動使用移動資料連線;
2.將微信設為忽略電池優化 設定>應用管理>設定>特殊訪問許可權>忽略電池優化>微信,設定為允許;
3.關閉省電模式 點選手機管家>剩餘xx%,關閉省電模式和超級省電的開關。
4.關閉省流量模式 手機管家>流量管理>省流量模式,關閉省流量模式;如果需要使用省流量模式,請開啟微信應用的開關,關閉後將無法在後臺接收新訊息。
5.開啟系統的通知功能 在設定>通知欄和狀態列>通知管理中找到微信,根據需要設定允許通知,以及通知方式(在狀態列、橫幅、鎖屏顯示通知);
6. 開啟微信應用內部的通知功能 在微信我>設定>新訊息提醒,開啟“接收新訊息通知”開關,並根據需要開啟或關閉“通知顯示訊息詳情”、“聲音”、“震動”。 :

場景2:如果開啟微信有地球介面,說明微信在後臺被殺,所以你無法及時收到訊息,你需要進行如下設定:
如果是EMUI8.X產品:
1.將微信設定為自動管理的應用:手機管家>剩餘xx%>啟動管理,將微信設定成自動管理。
2.系統提示微信高耗電提醒時,不要將應用直接關閉;
3.在使用手機管家>剩餘xx%中一鍵省電時,如果清理了微信,需要手動再次開啟微信。
4.超級省電模式下,微信會被關閉,如果手機電量充足,不需要使用超級省電時,最好關閉超級省電(手機管家>剩餘xx%)
如果是EMUI5.X產品:
1.將微信設定為後臺活躍應用和允許自啟動應用
  後臺活躍設定:手機管家>剩餘xx%>鎖屏清理應用,將微信設定成鎖屏後不清理;
自啟動應用設定:手機管家>自啟管理,將微信勾選成允許開機自動啟動;
2.系統提示微信高耗電提醒時,不要將應用直接關閉;
3.在使用手機管家>剩餘xx%中一鍵省電時,如果清理了微信,需要手動再次開啟微信。
4.超級省電模式下,微信會被關閉,如果手機電量充足,不需要使用超級省電時,最好關閉超級省電(手機管家>剩餘xx%)


六、結束語
想要徹底解決微信訊息延遲問題,除了配置上面的相關開關外,還需要微信、運營商網路、廠商省電策略這三個模組統一進行優化。這麼一看,還是2017年10月份工信部牽頭成立的"安卓統一推送聯盟"比較靠譜點。
按照工信部泰爾終端實驗室說法,未來將由終端廠商提供系統級推送服務,不再允許各 app 在後臺保留常連線。與此同時,各終端廠商實現推送通道介面和功能統一,方便開發者接入。在新標準下,訊息將通過統一的伺服器推送至使用者裝置,而不必喚醒應用,與 iOS 的機制類似。
雖道阻且長,但相信國內安卓環境會越來越好!