移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結

 

一、前言


本文接上篇《移動端IM開發者必讀(一):通俗易懂,理解移動網絡的「弱」和「慢」》,關於移動網絡的主要特性,在上篇中已進行過詳細地闡述,本文將針對上篇中提到的特性,結合咱們的實踐經驗,總結了四個方法來追求極致的「爽快」:快鏈路、輕往復、強監控、多異步,從理論講到實踐、從技術講到產品,理論聯繫實際,觸類旁通,但願給您帶來啓發

若是您還未閱讀完上篇《移動端IM開發者必讀(一):通俗易懂,理解移動網絡的「弱」和「慢」》,建議您先行讀完後再續本文。

本篇的目的,就是但願以通俗易懂的語言,幫助移動端IM開發者更好地針對性優化移動網絡的各類特性,使得開發出的功能給用戶帶來更好的使用體驗。

本文乃全網同類文章中,惟一內容最全、「糞」量最重者,請作好心理準備耐心讀下去,不要辜負做者已打上石膏的雙手和用廢的鍵盤。

另外,《現代移動端網絡短鏈接的優化手段總結:請求速度、弱網適應、安全保障》這篇文章也提到了本文所闡述的相關內容,強烈建議閱讀。php

學習交流:html

- 即時通信開發交流3羣:185926912[推薦]前端

- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM程序員

(本文同步發佈於:http://www.52im.net/thread-1588-1-1.html算法

二、系列文章


▼ 本文是《移動端IM開發者必讀》系列文章的第2篇:

編程


若是您是IM開發初學者,強烈建議首先閱讀《新手入門一篇就夠:從零開發移動端IM》。後端

三、相關文章


1)關於網絡通訊的基礎文章:

緩存


2)涉及移動端網絡特性的文章:

安全

 

四、優化方法一:「快鏈路」


咱們須要有一條(相對)快速、(相對)順暢、(相對)穩定的網絡通道承載業務數據的傳輸,這條路的最好是傳輸快、不擁堵、帶寬大、收費少。生活中作個類比,咱們計劃驅車從深圳到廣州,若是想固然走廣深高速十之八九要杯具,首先這個高速略顯破敗更像省道,路況不佳不敢提速;其次這條路上的車時常如過江之鯽,若是身材很差操控不便,根本就快不起來;最後雙向六車道雖然勉強能夠接受,但收費竟然比廣深沿江高速雙向八車道還貴;正確的選路方案目前看是走沿江高速,雖然可能要多跑一段里程,可是通行更暢快。

實際上,真實狀況要更復雜,就如同上篇中【圖二 有線互聯網和移動互聯網網絡質量差別】所示(就是下圖),漫漫征途中經常會在高速、國道、省道、田間小道上切換。

<ignore_js_op>移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結_11.jpg 

服務器

4.1TCP/IP協議棧參數調優


純技術活,直接上建議得了,每一個子項爭取能大體有個背景交待,若是沒說清楚,能夠先看看如下資料:
TCP/IP詳解 - 第17章·TCP:傳輸控制協議
TCP/IP詳解 - 第18章·TCP鏈接的創建與終止
TCP/IP詳解 - 第21章·TCP的超時與重傳
通俗易懂-深刻理解TCP協議(上):理論基礎
通俗易懂-深刻理解TCP協議(下):RTT、滑動窗口、擁塞處理
理論經典:TCP協議的3次握手與4次揮手過程詳解
鮮爲人知的網絡編程(一):淺析TCP協議中的疑難雜症(上篇)
鮮爲人知的網絡編程(二):淺析TCP協議中的疑難雜症(下篇)
鮮爲人知的網絡編程(三):關閉TCP鏈接時爲何會TIME_WAIT、CLOSE_WAIT
網絡編程懶人入門(三):快速理解TCP協議一篇就夠

① 控制傳輸包大小

控制傳輸包的大小在1400字節如下。暫時不講爲何這樣建議,先舉個例子來類比一下,好比一輛大卡車滿載肥豬正在高速上趕路,豬籠高高層疊好不壯觀,這時前方忽然出現一個隧道限高標識,司機發現卡車超限了,這下咋整。方案一,停車調頭從新找路,並且十之八九找不到,最後只能哪來回哪;方案二,把其中一羣豬卸下來放本地找人代養,到達目的地卸完貨回來再取,你別說,這個機制在TCP/IP協議棧中也有,學名「IP分片」,後面會專門介紹。這個故事側面證明美國計算機科學家也曾經蹲在高速路邊觀察生豬超載運輸的過程,並飽受啓發。且慢,每次遇到問題,想到一些方案後咱們都應該再捫心自問:「還有沒有更好的辦法呢?」。固然有,參照最近流行的說法,找個颱風眼,把豬都趕過去,飛一會就到了,此情此景想一想也是醉了。

迴歸正題,歸納的說,咱們設定1400這個閾值,目的是減小往復,提升效能。由於TCP/IP網絡中也有相似高速限高的規定,若是在超限時想要繼續順暢傳輸,要麼作IP分片要麼把應用數據拆分爲多個數據報文(意指由於應用層客戶端或服務器向對端發送的請求或響應數據太大時,TCP/IP協議棧控制機制自動將其拆分爲若干獨立數據報文發送的狀況,後面爲簡化討論,都以IP分片這個分支爲表明,相關過程分析和結論概括對兩者均適用)。而一旦一個數據報文發生了IP分片,便會在數據鏈路層引入屢次的傳輸和確認,加上報文的拆分和拼接開銷,令得整個數據包的發送時延大大增長,而且,IP分片機制中,任何一個分片出現丟失時還會帶來整個IP數據報文從最初的發起端重傳的消耗。有點枯燥了,更深刻的理解,請參見:《海量之道系列文章之弱聯網優化 (二)》。

咱們能夠得出以下結論,TCP/IP數據報文大小超過物理網絡層的限制時,會引起IP分片,從而增長時空開銷。

所以,設定合理的MSS相當重要,對於以太網MSS值建議是1400字節。什麼,你的數學是體育老師教的嗎?前面說以太網最大的傳輸數據大小是1500字節,IP數據報文包頭是20字節,TCP報文包頭是20字節,算出來MSS怎麼也得是1460字節呀。若是回答是由於不少路由設備好比CISCO路由器把MSS設定爲1400字節,大夥確定不幹,回憶一下IP和TCP的數據報包頭都各有40字節的可選項,MTU中還須要爲這些可選項留出空間,也就壓縮了MSS的空間。要是再追問爲啥這個值不是1380字節,那就有點過度了。

知識加油站:什麼是MSS?

TCP MSS(TCP Maximum Segment Size,TCP最大報文段長度,後面均簡稱MSS)表示TCP/IP協議棧一次能夠傳往另外一端的最大TCP數據長度,注意這個長度是指TCP報文中的有效「數據」(即應用層發出的業務數據)部分,它不包括TCP報文包頭部分,咱們能夠把它理解爲卡車能裝運生豬的最大數量或重量。它是TCP選項中最常常出現,也是最先出現的選項,佔4字節空間。

MSS是在創建TCP連接的三次握手過程當中協商的,每一方都會在SYN或SYN/ACK數據報文中通告其指望接收數據報文的MSS(MSS也只能出如今SYN或SYN/ACK數據報中),說是協商,其實也沒太多回旋的餘地,緣由一會講。若是協商過程當中一方不接受另外一方的MSS值,則TCP/IP協議棧會選擇使用默認值:536字節。


那麼問題來了,控制「限高」哪一種方案才最強。咱們嘗試探討一下。

首先,能夠在咱們本身IDC內將各類路由交換設備的MSS設定小於或等於1400字節,並積極參與TCP三次握手時的MSS協商過程,指望達到自動控制服務器收發數據報文大小不超過路徑最小MTU從而避免IP分片。這個方案的問題是若是路由路徑上其它設備不積極參與協商活動,而它的MTU(或MSS設置值)又比較low,那就白乾了。這就比如國家制定了一個高速沿途隧道限高公示通告標準,可是某些地方政府就是不告訴你,沒轍。

其次,能夠在業務服務中控制應用數據請求/響應的大小在1400字節如下(注:也沒法根本避免前述方案中間路由MTU/MSS low的問題),在應用層數據寫入時就避免往返數據包大小超過協商肯定的MSS。可是,歸根到底,在出發前就把數據拆分爲多個數據報文,同IP分片機制本質是相同的,交互響應開銷增長是必然的。考慮到人在江湖,安全第一,本方案從源頭上控制,顯得更實際一些。

固然,最靠譜的仍是作簡法,控制傳輸數據的慾望,用曼妙的身姿騰挪有致,相關的內容放到輕往復章節探討。

對應到前面的快樂運豬案例,就是要麼在生豬裝車以前我們按照這條路上的最低限高來裝車(問題是怎麼能知道整個路上的最低限高是多少),要麼按照國家標準規定容許的最小限高來裝車,到這裏,肥豬們終於能夠愉快的上路了,風和日麗,通行無阻,嗯,真的嗎?

② 放大TCP擁塞窗口

把TCP擁塞窗口(cwnd)初始值設爲10,這也是目前Linux Kernel中TCP/IP協議棧的缺省值。放大TCP擁塞窗口是一項有理有據的重要優化措施,對移動網絡尤爲重要,咱們一樣從一些基本理論開始逐步深刻理解它。

TCP是個傳輸控制協議,體現控制的兩個關鍵機制分別是基於滑動窗口的端到端之間的流量控制和基於RTT/RTO測算的端到網絡之間的擁塞控制。

流量控制目標是爲了不數據發送太快對端應用層處理不過來形成SOCKET緩存溢出,就像一次發了N車肥豬,買家那邊來不及處理,而後臨時囤貨的豬圈又已客滿,只好拒收/拋棄,相關概念和細節咱們不展開了,有興趣能夠研讀《TCP/IP詳解 卷一:協議》。

擁塞控制目標是在擁塞發生時能及時發現並經過減小數據報文進入網絡的速率和數量,達到防止網絡擁塞的目的,這種機制能夠確保網絡大部分時間是可用的。擁塞控制的前提在於能發現有網絡擁塞的跡象,TCP/IP協議棧的算法是經過分組丟失來判斷網絡上某處可能有擁塞狀況發生,評判的具體指標爲分組發送超時和收到對端對某個分組的重複ACK。在有線網絡時代,丟包發生確實能比較肯定的代表網絡中某個交換設備故障或由於網絡端口流量過大,路由設備轉發處理不及時形成本地緩存溢出而丟棄數據報文,但在移動網絡中,丟包的狀況就變得很是複雜,其它因素影響和干擾形成丟包的機率遠遠大於中間路由交換設備的故障或過載。好比短期的信號干擾、進入一個信號屏蔽的區域、從空閒基站切換到繁忙基站或者移動網絡類型切換等等。網絡中增長了這麼多不肯定的影響因素,這在TCP擁塞控制算法最初設計時,是沒法預見的,同時,咱們也確信將來會有更完善的解決方案。這是題外話,若有興趣能夠找些資料深刻研究(詳見:《TCP/IP詳解 - 第21章·TCP的超時與重傳》、《通俗易懂-深刻理解TCP協議(下):RTT、滑動窗口、擁塞處理》、《海量之道系列文章之弱聯網優化 (三)》)。

擁塞控制是TCP/IP協議棧最經典的和最複雜的設計之一,互聯網自我犧牲的利他精神表露無遺,設計者認爲,在擁塞發生時,咱們應該減小數據報文進入網絡的速率和數量,主動讓出道路,令網絡能儘快調整恢復至正常水平。

③ 調大SOCKET讀寫緩衝區

把SOCKET的讀緩衝區(亦可稱爲發送緩衝區)和寫緩衝區(亦可稱爲接收緩衝區)大小設置爲64KB。在Linux平臺上,能夠經過 setsockopt 函數設置SO_RCVBUF和SO_SNDBUF選項來分別調整SOCKET讀緩衝區和寫緩衝區的大小。

這兩個緩衝區跟咱們的TCP/IP協議棧到底有怎麼樣的關聯呢。咱們回憶一下TCP數據報格式及首部中的各字段裏面有個16位窗口大小(見下圖),還有咱們前面提到的流量控制機制和滑動窗口的概念,大幕徐徐拉開,主角紛紛粉墨登場。在正式詳細介紹以前,按照傳統,咱們仍是先站在豬場老闆的角度看一下,讀緩衝區就比如買家用來囤貨的臨時豬圈,若是貨到了買家使用部門來不及處理,就先在這裏臨時囤着,寫緩衝區就比如養豬場根據訂單裝好車準備發貨,若是買家說我如今能夠收貨即可速度發出,有點明白了吧。

<ignore_js_op>移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結_222.png 

④ 調大RTO(Retransmission TimeOut)初始值

將RTO(Retransmission TimeOut)初始值設爲3s。

TCP爲每個報文段都設定了一個定時器,稱爲重傳定時器(RTO),當RTO超時且該報文段尚未收到接收端的ACK確認,此時TCP就會對該報文段進行重傳。當TCP鏈路發生超時時,意味着極可能某個報文段在網絡路由路徑的某處丟失了,也所以判斷此時網絡出現擁塞的可能性變得很大,TCP會積極反應,立刻啓動擁塞控制機制。

RTO初始值設爲3s,這也是目前Linux Kernel版本中TCP/IP協議棧的缺省值,在鏈路傳輸過程當中,TCP協議棧會根據RTT動態從新計算RTO,以適應當前網絡的情況。有不少的網絡調優方案建議把這個值儘可能調小,可是,咱們開篇介紹移動網絡的特色之一是高時延,這也意味着在一個RTT比較大的網絡上傳輸數據時,若是RTO初始值太小,極可能發生沒必要要的重傳,而且還會由於這個事件引發TCP協議棧的過激反應,大炮一響,擁塞控制閃亮登場。

豬場老闆的態度是什麼樣的呢:曾經有一份按時發貨的合同擺在個人面前,我沒有去注意,等到從新發了貨才追悔莫及,塵世間最痛苦的事莫過於此,若是上天能給我一個再來一次的機會,我但願對甲方說耐心點,若是非要給這個耐心加一個期限的話,我但願是一萬年。

⑤ 禁用TCP快速回收


TCP快速回收是一種連接資源快速回收和重用的機制,當TCP連接進入到TIME_WAIT狀態時,一般須要等待2MSL的時長,可是一旦啓用TCP快速回收,則只需等待一個重傳時間(RTO)後就可以快速的釋放這個連接,以被從新使用。

Linux Kernel的TCP/IP協議棧提供了一組控制參數用於配置TCP端口的快速回收重用,當把它們的值設置爲1時表示啓用該選項:

  • 1)  net.ipv4.tcp_tw_reuse = 1
  • 2) net.ipv4.tcp_tw_recycle = 1
  • 3)  net.ipv4.tcp_timestamps = 1(tcp_tw_recycle啓用時必須同時啓用本項,反之則否則,timestamps用於RTT計算,在TCP報文頭部的可選項中傳輸,包括兩個參數,分別爲發送方發送TCP報文時的時間戳和接收方收到TCP報文響應時的時間戳。Linux系統和移動設備上的Android、iOS都缺省開啓了此選項,建議不要隨意關閉)


以上參數中tw是TIME_WAIT的縮寫,TIME_WAIT與TCP層的連接關閉狀態機相關。具體TIME_WAIT是誰,從哪裏來,往哪裏去,能夠詳見:《海量之道系列文章之弱聯網優化 (四)》。

⑥ HTTP協議:打開SOCKET的TCP_NODELAY選項

TCP/IP協議棧爲了提高傳輸效率,避免大量小的數據報文在網絡中流竄形成擁塞,設計了一套相互協同的機制,那就是Nagle's Algorithm和TCP Delayed Acknoledgement。

Nagle算法(Nagle's Algorithm)是以發明人John Nagle的名字來命名。John Nagle在1984年首次用這個算法來嘗試解決福特汽車公司的網絡擁塞問題(RFC 896),該問題的具體描述是:若是咱們的應用程序一次產生1個字節的數據(典型的如telnet、XWindows等應用),而這個1個字節數據又以網絡數據包的形式發送到遠端服務器,那麼就很容易使網絡中有太多微小分組而致使過載。

由於傳輸1個字節有效數據的微小分組卻需花費40個字節的額外開銷(即IP包頭20字節 + TCP包頭20字節),這種有效載荷利用率極其低下的狀況被統稱爲愚蠢窗口症候羣(Silly Window Syndrome),前面咱們在談MSS時也提到過,若是爲一頭豬開個大卡車跑一趟,也夠愚鈍的。對於輕負載廣域網或者局域網來講,尚可接受,可是對於重負載的廣域網而言,就極有可能引發網絡擁塞致使癱瘓。

現代TCP/IP 協議棧默認幾乎都啓用了這兩個功能。

咱們在移動APP的設計實現中,請求大部分都很輕(數據大小不超過MSS),爲了不上述分析的問題,建議開啓SOCKET的TCP_NODELAY選項,同時,咱們在編程時對寫數據尤爲要注意,一個有效指令作到一次完整寫入(後面會講協議合併,是多個指令一次完整寫入的設計思想),這樣服務器會立刻有響應數據返回,順便也就捎上ACK了。

4.2接入調度


① 就快接入

在客戶端接入服務器調度策略的演化過程當中,咱們最先採用了「就近接入」的策略,在距離客戶端更近的地方部署服務器或使用CDN,指望經過減小RTT來提升網絡交互響應性能。這個策略在國內的落地執行還須要加一個前綴:「分省分運營商」,這就給廣大負責IDC建設的同窗帶來了巨大的精神和肉體折磨。

在持續運營的過程當中,根據觀察到的數據,發現並不是物理距離最近的就是最快的。回憶一下前面談到的吞吐量指標BDP,它與鏈路帶寬和RTT成正比關係,而RTT是受物理距離、網絡擁塞程度、IDC吞吐量、跨網時延等諸多因素綜合影響的,單純的就近顯然不夠精細了。

「就快接入」在「就近接入」策略的基礎上改善提高,它利用客戶端測速和報告機制,經過後臺大數據分析,造成與客戶端接入IP按就快原則匹配接入服務器的經驗調度策略庫,令客戶端總能優先選擇到最快的服務器接入點。

有關就快接入的更詳細方案,請參見:《海量之道系列文章之弱聯網優化(五)》一文的「3.1.2節」。

② 去DNS的IP直連

DNS不但須要1個RTT的時間消耗,並且移動網絡下的DNS還存在不少其它問題:

  • 1) 部分DNS承載全網用戶40%以上的查詢請求,負載重,一旦故障,影響巨大,這樣的案例在PC互聯網也有不少,Google一下便可感覺觸目驚心的效果;
  • 2) 山寨、水貨、刷ROM等移動設備的LOCAL DNS設置錯誤;
  • 3) 終端DNS解析濫用,致使解析成功率低;
  • 4) 某些運營商DNS有域名劫持問題,實際上有線ISP也存在相似問題。域名劫持對安全危害極大,產品設計時要注意服務端返回數據的安全校驗(若是協議已經創建在安全通道上時則不用考慮,安全通道能夠基於HTTPS或者私有安全體系)。對於劫持的判斷須要客戶端報告實際拉取服務數據的目標地址IP等信息;
  • 5) DNS污染、老化、脆弱。


綜上就是在前述就快接入小節中,接入調度FSM會優先使用動態服務器列表的緣由。

③ 網絡可達性探測

在鏈接創建過程當中若是出現鏈接失敗的現象,而終端系統提供的網絡狀態接口反饋網絡可用時,咱們須要作網絡可達性探測(即向預埋的URL或者IP地址發起鏈接嘗試),以區別網絡異常和接入服務異常的狀況,爲定位問題,優化後臺接入調度作數據支持。

探測數據能夠異步報告到服務器,至少應該包含如下字段:

  • 1) 探測事件ID,要求全局惟一不重複;
  • 2) 探測發生時間;
  • 3) 探測發生時網絡類型和其它網絡信息(好比WIFI時的SSID等);
  • 4) 本地調度的接入服務器集合類型;
  • 5) 本地調度的接入服務器IP(如使用域名接入,可忽略);
  • 6) 探測的目標URL或IP地址
  • 7) 本次探測的耗時。

 

4.3鏈路管理


鏈路就是運肥豬的高速路,就快接入是選路,鏈路管理就是如何高效的使用這條路。下面是一些實踐總結:

① 鏈路複用

咱們在開篇討論無線網絡爲何慢的時候,提到了連接創建時三次握手的成本,在無線網絡高時延、頻抖動、窄帶寬的環境下,用戶使用趨於碎片化、高頻度,且請求響應又一次性往返居多、較頻繁發起等特徵,建鏈成本顯得尤爲顯著。

所以,咱們建議在鏈路建立後能夠保持一段時間,好比HTTP短連接能夠經過HTTP Keep-Alive,私有協議能夠經過心跳等方式來保持鏈路。

具體要點建議以下:

  • 1) 鏈路複用時,若是服務端按就快策略機制下發了新的接入動態服務器列表,則應該按照接入調度FSM的狀態變遷,在本次交互數據完成後,重建與新的接入服務器的IP鏈路,有三個切換方案和時機可選擇:
        - a. 關閉原有連接,暫停網絡通信,同時開始創建與新接入服務器的TCP鏈路,成功後恢復與服務器的網絡交互;
        - b. 關閉原有連接,暫停網絡通信,待有網絡交互需求時開始創建與新接入服務器的IP鏈路;
        - c. 原有連接繼續工做,並同時開始創建與新接入服務器的TCP鏈路,成功後新的請求切換到新建鏈路上,這個方式或可稱爲預建連接,原連接在空閒時關閉。
  • 2) 鏈路複用時區分輕重數據通道,對於業務邏輯等相關的信令類輕數據通道建議複用,對於富媒體拉取等重數據通道就沒必要了;
  • 3) 鏈路複用時,如與協議合併(後面會討論)結合使用,效果更佳。


② 區分網絡類型的超時管理

在不一樣的網絡類型時,咱們的鏈路超時管理要作精細化的區別對待。鏈路管理中共有三類超時,分別是鏈接超時、IO超時和任務超時。

咱們有一些經驗建議,提出來共同探討:

  • 1) 鏈接超時:2G/3G/4G下5 ~ 10秒,WIFI下5秒(給TCP三次握手留下1次超時重傳的機會,能夠研究一下《TCP/IP詳解 卷一:協議》中TC P的超時與重傳部分);
  • 2) IO超時:2G/3G/4G下15 ~ 20秒(無線網絡不穩定,給抖動留下必要的恢復和超時重傳時間),WIFI下15秒(1個MSL);
  • 3) 任務超時:根據業務特徵不一樣而差別化處理,總的原則是前端面向用戶交互界                     面的任務超時要短一些(儘可能控制在30秒內並有及時的反饋),後臺任務能夠長一些,輕數據能夠短一些,重數據能夠長一些;
  • 4) 超時老是伴隨着重試,咱們要謹慎當心的重試,後面會討論。


超時時間宜短不宜長,在一個合理的時間內令當前鏈路因超時失效,從而驅動調度FSM狀態的快速變遷,效率要比癡癡的等待高得多,同時,在用戶側也能獲得一個較好的正反饋。

各種超時參數最好能作到雲端可配可控。

③ 優質網絡下的併發鏈路

當咱們在4G、WIFI(要區分是WIFI路由器仍是手機熱點)等網絡條件較優時,對於請求隊列積壓任務較多或者有重數據(富媒體等下載類數據)請求時,能夠考慮併發多個鏈路並行執行。

對於單一重數據任務的多連接併發協同而言,須要服務器支持斷點續傳,客戶端支持任務協同調度;

④ 輕重鏈路分離


輕重鏈路分離,也能夠說是信令和數據分離,目的是隔離網絡通信的過程,避免重數據通信延遲而阻塞了輕數據的交互。在用戶角度看來就是信息在異步加載,控制指令響應反饋及時。

移動端大部分都是HTTP短連接模式工做,輕重數據的目標URL自己就不一樣,比較自然的能夠達到分離的要求,可是仍是要特別作出強調,是由於實踐中有些輕數據協議設計裏面還會攜帶相似頭像、驗證碼等的實體數據。

⑤ 長連接

長連接對於提高應用網絡交互的及時性大有裨益,一方面用戶使用時,節省了三次握手的時間等待,響應快捷;另外一方面服務器具有了實時推送能力,不但能夠及時提示用戶重要信息,並且能經過推拉結合的異步方案,更好的提高用戶體驗。

長連接的維護包括連接管理、連接超時管理、任務隊列管理等部分,設計實施複雜度相對高一些,尤爲是在移動網絡環境下。爲了保持鏈路還須要作心跳機制(從另一個角度看,這也是針對簡單信息一個不錯的PULL/PUSH時機,,但需注意數據傳輸要夠輕,好比控制在0.5KB之內),而心跳機制是引入長連接方案複雜度的一個重要方面,移動網絡鏈路環境複雜,國內網關五花八門,鏈路超時配置各有千秋,心跳時長選擇學問比較大,不但要區分網絡類型,還得區分不一樣運營商甚至不一樣省市,歷史上曾經實踐了2分鐘的心跳間隔,最近比較多的產品實踐選擇4.5分鐘的心跳間隔。並且長連接除了給移動網絡尤爲是空中信道帶來負擔外,移動設備自身的電量和流量也會有較大的消耗,同時還帶來後端帶寬和服務器投入增長。

因此,除了一些粘性和活躍度很高、對信息到達實時性要求很高的通信類APP外,建議謹慎使用長連接,或能夠考慮採用下面的方式:

  • 1)  退化長連接:即用戶在前臺使用時,保持一個長連接鏈路,活躍時經過用戶使用驅動網絡IO保持鏈路可用;靜默時經過設置HTTP Keep-Alive方式,亦或經過私有協議心跳方式來保持鏈路。一旦應用切換後臺,且在5~10分鐘內沒有網絡交互任務則自行關閉鏈路,這樣在用戶交互體驗和資源消耗方面取得一個平衡點;
  • 2)  定時拉取/詢問:對於一些有PUSH需求的APP,咱們能夠採用一個雲端可配置間隔時長的定時拉取/詢問方案。有三個重點,一是定時的間隔雲端能夠配置,下發更新到客戶端後下次生效;二是拉取/詢問時,若是下發的指令有要求進一步PULL時,能夠複用已創建的鏈路,即前述退化長連接的模式;三是定時拉取/詢問時機在客戶端要作時間上的均勻離散處理,避免大的併發查詢帶來帶寬和負載的巨大毛刺;
  • 3) 若是可能,優先使用OS內置的PUSH通道:好比iOS的APNS、Andriod的 GCM(Google這個以工程師文化著稱的公司,在作OS級基礎設施建設時,卻表現出了不好的前瞻性和系統思考的能力,GCM的前身C2DM都沒怎麼普及使用就被替換了,這也意味着Android各類版本PUSH能力不 一致的問題。但不管怎麼說,OS級的基礎設施不管在性能、穩定性仍是在效率上都會優於APP層本身實現的方案),實施推拉結合的方案。特別要提到的一點是,中國特點無所不在,國內運營商曾經封過APNS的PUSH端口2195,也會干擾GCM的端口5528,更別提這些底層服務的長連接會被運營商干擾。對於Android平臺,還存在系統服務被各類定製修改的問題。別擔憂,辦法總比問題多,保持清醒。


有關Android的推送問題,能夠參考:
應用保活終極總結(三):Android6.0及以上的保活實踐(被殺復活篇)
Android進程保活詳解:一篇文章解決你的全部疑問
Android端消息推送總結:實現原理、心跳保活、遇到的問題等
深刻的聊聊Android消息推送這件小事
爲什麼基於TCP協議的移動端IM仍然須要心跳保活機制?
微信團隊原創分享:Android版微信後臺保活實戰分享(網絡保活篇)
移動端IM實踐:實現Android版微信的智能心跳機制
移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》)

⑥ 當心重試

自動重試是致使後臺雪崩的重要因素之一。在移動網絡不穩定的條件下,大量及時的重試不但不能達到預期,反而無謂的消耗移動設備的電量甚至流量。

所以,咱們在重試前要有一些差別化的考慮:

  • 1) 當前移動設備的網絡情況如何,若是沒有網絡,則沒必要重試;
  • 2) 重試設定必要的時間間隔,由於移動接入網絡抖動到恢復可能須要一點時間,立刻重試並不是最佳策略,反而可能無謂的消耗電量。實踐中,能夠在一次鏈接或IO失敗(當即失敗或超時)時,過3 ~ 5秒後再試;
  • 3)  重試應設定必要的總時限,由於三個服務器列表比較長,每一個服務器地址都要重試和等待若干次,最終可能致使接入調度FSM和服務器列表調度FSM流轉耗時過長,此時用戶側體驗表現爲長時間等待無響應。總時限參數能夠參考前述區分網絡類型的超時管理中的任務超時值。一旦某次重試成功,重試總時限計時器要歸零;
  • 4) 服務器下發特定錯誤碼(好比服務器故障、過載或高負載)時,提示客戶端中止重試並告知安撫用戶,咱們在強監控這個主題下有詳細的討論。


每一個目標服務器地址的重試次數、重試總時限和重試時間間隔最好能作到雲端可配可控。

特別須要提出的一點是,移動APP採用HTTP短連接模式實現CS交互時,普遍的使用了系統原生組件或者開源組件,這些友好的模塊把超時和重試都封裝起來,其缺省值是否適合本身的業務特色,須要多多關注。使用前,最好能知其然更知其因此然。

⑦ 及時反饋

透明和尊重,會帶來信任和默契,家庭如此、團隊如此、用戶亦如此。此地無銀三百兩和裝傻充愣也許短暫取巧,拉長時間軸來看,確定要付出慘重的代價。及時和真誠的告知情況,贏得諒解和信任,小付出,大回報,試過都知道。

當發現由於網絡不存在或者其它屬於移動端設備鏈路的異常時,應該及時和顯著的提示用戶,讓用戶注意到當前有諸如網絡不存在、FREE WIFI接入認證頁面需確認等等問題,使用戶能夠及時處理或理解問題狀態。

當發現是服務器問題時,應及時、顯著和真誠的告知用戶,爭取用戶的諒解。

網絡異常提示或服務器故障通告等信息的呈現要作到一目瞭然,無二義和二次交互。

4.4IO管理


基於一個快速和高效管理的鏈路之上,作好IO調度和控制,也是提高效能和改善用戶體驗的重要環節。

要探討的內容包括:

① 異步IO

異步化IO的目的就是避免資源的集中競爭,致使關鍵任務響應緩慢。咱們在後面差別服務個大的分類中會重點探討。這裏特別先提出來,是建議在程序架構頂層設計時,要在總體機制上支持異步化,設計必要的異步總線來聯繫各個層級模塊,總線可能會涉及包括隊列管理(優先級、超時、CRUD等)、事件驅動、任務調度等。

異步IO除了網絡方面外,對移動設備,咱們還特別要考慮一下磁盤IO的異步。由於頻繁、大吞吐量的磁盤IO會形成APP的UI卡頓,從用戶體驗上看就是交互響應遲鈍或者滑動幀率降低。通常來講,磁盤IO異步會選用空間換時間的方案,即緩存數據批量定時寫入磁盤。

② 併發控制

有了異步IO,併發控制就顯得尤其重要。把異步機制看成銀彈任意使用,就如同咱們給移動APP設計了一個叫「發現」的地方同樣,極可能各類膨脹的需求、不知道如何歸類的需求就紛至沓來,期待有朝一日被「發現」。

異步IO提供了一個很好的發射後不用管的機制,這就會形成使用者的膨脹,不管是否必要、不管輕重緩急,把請求一股腦的丟給異步隊列,本身瀟灑的轉身就走。這樣不但會帶來效率和交互響應性能的降低,也會形成資源的無謂消耗。

在後面多異步這個大分類的討論中會涉及到輕重緩急的話題,在前述異步IO的磁盤IO的時空效率轉換話題中,還應該包括IO併發的控制,咱們即不能由於併發過多的鏈路形成網絡帶寬的獨佔消耗影響其它APP的使用,也不可因快速、大量的異步數據形成緩寫機制形同虛設或是佔用過大的內存資源。

③ 推拉結合

PUSH機制應該是蘋果公司在移動設備上取得輝煌成就的最重要兩個機制之一,另一個是移動支付體系。咱們這裏的討論不包括iOS和APPLE移動設備的擬人化交互體驗,只側重根基性的機制能力。APNS解決了信息找人的問題,在過去,只有運營商的短信有這個能力,推送和拉取使得咱們具有了實時獲取重要信息的能力。

爲什麼要推拉結合。由於系統級的推送體系也必須維持一個本身的鏈路,而這個鏈路上要承載五花八門的APP推送數據,若是過重,一方面會在設計上陷入個性化需求的繁瑣細節中,另一方面也會形成這條鏈路的擁堵和性能延遲。所以,經過PUSH通知APP,再由APP經過本身的鏈路去PULL數據,即有效的利用了PUSH機制,又能使得APP能按需使用網絡,不但簡化了鏈路管理,並且節省了電量和流量。

④ 斷點續傳

一方面,在討論鏈路管理時,咱們建議了優質網絡下的併發鏈路來完成同一個重數據拉取任務。這就會涉及到任務的拆分和並行執行,基礎是後臺能支持斷點續傳。

另一方面,從客戶端的角度而言,移動網絡的不穩定特色,可能會形成某個重數據拉取任務忽然失敗,不管是自動重試仍是用戶驅動的重試,若是能從上次失效的上下文繼續任務,會有省時間、省電量和省流量的效果,想一想也會以爲十分美好。

五、優化方法二:「輕往復」


「技」止此爾。強調網絡交互的「少」,更應強調網絡交互的「簡」。

咱們在一條高時延易抖動的通道上取得效率優點的關鍵因素就是減小在其上的往復交互,最好是老死不相往來(過激),而且這些往復中交換的數據要儘可能的簡潔、輕巧,輕車簡從。這個概念是否是有點像多幹多錯,少幹少錯,不幹沒錯。

把咱們實踐過的主要手段提出來探討:

① 協議二進制化

二進制比較緊湊,可是可讀性差,也所以造成可維護性和可擴展性差、調測不便的不良印象。這也形成了大量可見字符集協議的出現。計算機是0和1的世界,她們是程序猿的水和電,任何一個整不明白,就無法愉快的生活了。

② 高效協議

高效的協議能夠從兩個層面去理解,一是應用層標準協議框架,二是基於其上封裝的業務層協議框架,有時候也能夠根據須要直接在TCP之上把這兩個層面合併,造成純粹的業務層私有協議框架。不過,爲了簡化網絡模塊的通信機制和一些通用性、兼容性考慮,目前大多數狀況下,咱們都會選擇基於HTTP這個應用層標準協議框架之上承載業務層協議框架。下面咱們針對上述兩個層面展開探討。

首先是應用層的標準協議優化:好比HTTP/1.1的Pipeline、WebSocket(在HTML5中增長)、SPDY(由Google提出)、HTTP/2等,其中特別須要關注的是處在試驗階段的SPDY和草案階段的HTTP/2。

SPDY是Google爲了規避HTTP/1.1暨之前版本的侷限性開展的試驗性研究,主要包括如下四點:

  • 1) 鏈路複用能力:HTTP協議最先設計時,選擇了一問一答一鏈接的簡單模式,這樣對於有不少併發請求資源或連續交互的場景,鏈路創建的數量和時間成本就都增長了;
  • 2) 異步併發請求的能力:HTTP協議最先的設計中,在拉取多個資源時,會對應併發多個HTTP鏈路(HTTP/1.1的Pipeline相似)時,服務端沒法區分客戶端請求的優先級,會按照先入先出(FIFO)的模式對外提供服務,這樣可能會阻塞客戶端一些重要優先資源的加載,而在鏈路複用的通道上,則提供了異步併發多個資源獲取請求指令的能力,而且能夠指定資源加載的優先級,好比CSS這樣的關鍵資源能夠比站點ICON之類次要資源優先加載,從而提高速度體驗;
  • 3) HTTP包頭字段壓縮:(注:特指字段的合併刪減,並不是壓縮算法之意)精簡,HTTP協議中HEAD中字段多,冗餘大,每次請求響應都會帶上,在很多業務場景中,傳遞的有效數據尺寸遠遠小於HEAD的尺寸,帶寬和時間成本都比較大,並且很浪費;
  • 4) 服務器端具有PUSH能力:服務器能夠主動向客戶端發起通訊向客戶端推送數據。


HTTP/2由標準化組織來制定,是基於SPDY的試驗成果開展的HTTP協議升級標準化工做,有興趣瞭解詳細狀況能夠參考HTTP/2的DRAFT文檔。

其次是業務層的協議框架優化:它能夠從三個方面考察

  • 一是協議處理性能和穩定性好,包括諸如協議緊湊佔用空間小,編碼和解碼時內存佔用少CPU消耗小計算快等等,而且bad casae很是少;
  • 二是可擴展性好,向下兼容自沒必要說,向上兼容也並不是不能;
  • 三是可維護性強,在協議定義、接口定義上,作到可讀性強,把二進制協議以可讀字符的形式展現,再經過預處理轉化爲源碼級文件參與工程編譯。


可能會有同窗強調協議調測時的可閱讀、可理解,既然讀懂01世界應該是程序員的基本修養,這一項可能就沒那麼重要了。

高效的業務層協議框架從分佈式系統早期表明Corba的年代就有不少不錯的實踐項目,目前最流行的開源組件應屬ProtoBuf,能夠學習借鑑。

正所謂異曲同工、心有靈犀、不謀而合,英雄所見略同......,說來講去,高效協議的優化思路也都在鏈路複用、推拉結合、協議精簡、包壓縮等等奇技淫巧的範疇以內。

有關Protobuf等技術的詳細文章,請參見:
Protobuf通訊協議詳解:代碼演示、詳細原理介紹等
如何選擇即時通信應用的數據傳輸格式
強列建議將Protobuf做爲你的即時通信應用數據傳輸格式
全方位評測:Protobuf性能到底有沒有比JSON快5倍?
移動端IM開發須要面對的技術問題(含通訊協議選擇)
簡述移動端IM開發的那些坑:架構設計、通訊協議和客戶端
理論聯繫實際:一套典型的IM通訊協議設計詳解
58到家實時消息系統的協議設計等技術實踐分享
技術掃盲:新一代基於UDP的低延時網絡傳輸層協議——QUIC詳解
金蝶隨手記團隊分享:還在用JSON? Protobuf讓數據傳輸更省更快(原理篇)
金蝶隨手記團隊分享:還在用JSON? Protobuf讓數據傳輸更省更快(實戰篇)

③ 協議精簡

協議精簡的目的就是減小無謂的數據傳輸,提高網絡效能。俗話說「千里不捎針」,古人誠不我欺也。

咱們實踐總結如下三點供參考:

  • 1) 能不傳的就不傳:把須要的和但願有的數據都列出來,按照對待產品需求的態 度,先砍掉一半,再精簡一半,估計就差很少了。另外,高效協議提供了比較好的擴展性,預留字段越少越好,移動互聯網演化很是快,常常會發現前瞻的預留老是趕不上實際的需求;
  • 2) 抽象公共數據:把各協議共性的屬性數據抽象出來,封裝在公共數據結構中, 即所謂包頭一次就傳一份,這個想法不新鮮,TCP/IP的設計者們早就身體力行了。除了帶來數據冗餘的下降外,還下降了維護和擴展的複雜度,一石二鳥,且抽且行;
  • 3) 多用整數少用字符:數字比文字單純,即簡潔又清晰,還不須要擔憂英文很差被後繼者BS;
  • 4) 採用增量技術:通知變化的數據,讓接收方處理差別,這是個很好的設計思想,實踐中須要注意數據一致性的校驗和保障機制,後面會有專門的細節討論。


④ 協議合併

協議合併的目標是經過將多條交互指令歸併在一個網絡請求中,減小鏈路建立和數據往復,提高網絡效能。

把實戰總結的六點提出來供參考:

  • 1) 協議合併結合協議精簡,效率翻番;
  • 2) 協議合併的基礎是業務模型的分析,在分類的基礎上去作聚合。首先得區分出來緩急,把實時和異步的協議分類出來分別去合併;其次得區分出來輕重,協議請求或協議響應的數據規模(指壓縮後),儘可能確保在一個數據報文中可完成推拉;
  • 3) 協議合併在包的封裝上至少有兩種選擇,一是明文協議合併後統一打包(即壓縮和解密);二是明文協議分別打包,最後彙總;前者效率高一些,在實戰中用的也較廣泛;後者爲流式處理提供可能;
  • 4) 協議合併對服務器的異步處理架構和處理性能提出了更高的要求,特別須要權衡網絡交互效率和用戶對後臺處理返回響應期待之間的取捨;
  • 5) 協議間有邏輯順序關係時,要認真考慮設計是否合理或可否合併;
  • 6) 重數據協議不要合併。


⑤ 增量技術

增量技術準確分類應該算是協議精簡的一個部分,它與業務特色結合的很是緊密,值得單獨討論一下。增量技術在CS數據流交互比較大的時候有充分發揮的空間,由於這個技術會帶來客戶端和服務器計算、存儲的架構複雜度,增長資源消耗,而且帶來許多保障數據一致性的挑戰,固然,咱們能夠設計的更輕巧,允許一些不一致。

咱們用一個案例來看看增量技術的運用。

在應用分發市場產品中,都有一個重要功能,叫更新提醒。它的實現原理很簡單,以Android設備爲例,客戶端把用戶移動設備上安裝的APP包名、APP名稱、APP簽名、APP版本號等信息發送到服務器,服務器根據這些信息在APP庫中查找相應APP是否有更新並推送到客戶端。這個過程很是簡單,但若是用戶手機上裝了50個APP,網絡上交互的數據流就很是客觀了,即浪費流量和電量,又形成用戶體驗的緩慢,顯得很笨重。

這個時候,增量技術就能夠派上用場了,好比下面的方案:

  • 1) 每一個天然日24小時內,客戶端選擇一個時間(優先選擇駐留在後臺的時候)上報一次全量數據;
  • 2) 在該天然日24小時的其它時間,客戶端能夠定時或在用戶使用時發送增量數據,包括卸載、安裝、更新升級等帶來的變化;
  • 3) 做爲弱一致性的保障手段,客戶端在收到更新提示信息後,根據提醒的APP列表對移動設備上實際安裝和版本狀況作一次覈對;
  • 4) 上述擇機或定時的時間均可以由雲端經過下發配置作到精細化控制。


⑥ 包壓縮

前面精打細算完畢,終於輪到壓縮算法上場了。選擇什麼算法,中間有哪些實戰的總結,下面提出來一塊兒探討:

  • 1) 壓縮算法的選擇:咱們比較熟悉的壓縮算法deflate、gzip、bzip二、LZO、Snappy、FastLZ等等,選擇時須要綜合考慮壓縮率、內存和CPU的資源消耗、壓縮速率、解壓速率等多個緯度的指標,對於移動網絡和移動設備而言,建議考慮使用gzip。另外須要注意的是,輕數據與重數據的壓縮算法取捨有較大差別,不可一律而論;
  • 2) 壓縮和加密的前後秩序:通常而言,加密後的二進制數據流壓縮率會低一些,建議先壓縮再加密;
  • 3) 注意一些協議組件、網絡組件或數據自己是否已經作過壓縮處理,要避免重複工做,不要形成性能和效率的降低:好比一些圖片格式、視頻或APK文件都有本身的壓縮算法。


說到這,問題又來了,若是應用層標準協議框架作了壓縮,那麼基於其上封裝的業務層協議框架還須要壓縮嗎,壓縮技術到底哪家強?這個問題真很差回答,考慮到HTTP/2這樣的應用層標準協議框架定稿和普及尚需時日,建議在業務層協議框架中作壓縮機制。或者追求完美,根據後端應用層標準協議框架響應是否支持壓縮及在支持時的壓縮算法如何等信息,動態安排,總的原則就是一個字:只選對的,不選貴的。

五、優化方法三:「強監控」


可監方可控,咱們在端雲之間,要造成良好的關鍵運營數據的採集、彙總和分析機制,更須要設計雲端可控的配置和指令下發機制。

本篇重點討論與主題網絡方面相關關鍵指標的「監」和「控」

以就快接入爲例來探討一下強監控能力的構建和使用:

  • 1) 接入質量監控:客戶端彙總接入調度FSM執行過程元信息以及業務請求響應結果的元信息,並由此根據網絡類型不一樣、運營商不一樣、網絡接入國家和省市不一樣分析接入成功率、業務請求成功率(還可細化按業務類型分類統計)、前述兩者失敗的緣由歸類、接入302重定向次數分佈暨緣由、接入和業務請求測速等;
  • 2) 建設雲端可控的日誌染色機制:便於快速有針對性的定點排查問題;
  • 3) 終端硬件、網絡狀態的相關參數採集彙總;
  • 4) 建設雲端可控的接入調度(好比接入IP列表等)和網絡參數(好比鏈接超時、IO超時、任務超時、併發連接數、重試間隔、重試次數等)配置下發能力;
  • 5) 服務器根據彙總數據。


經過數據分析,結合服務器自身的監控機制,能夠作到:

  • a. 支持細粒度的接入調度和網絡參數的優化雲控;
  • b. 支持服務器的部署策略優化;
  • c. 發現移動運營商存在的一些差別化問題好比URL劫持、網絡設備超時配置不當等問題便於推進解決;
  • d. 發現分省市服務器服務質量的異常狀況,能夠動態雲端調度用戶訪問或者降級服務,嚴重時能夠及時提示客戶端發出異常安撫通告,避免加重服務器的負載致使雪崩。安民告示的快速呈現能力,考驗了一個團隊對可「控」理解的深度,咱們在實踐中,提供了三級措施來保障:
        - 第一級是服務器端經過協議或跳轉URL下發的動態通告,這在非IDC公網故障且業務接入服務器正常可用時適用;
        - 第二級是預埋靜態URL(能夠是域名或IP形式,優先IP)拉取動態通告,適用其它故障,靜態URL部署的IP地址最好同本業務系統隔離,避免由於業務服務所在IDC公網故障不可用時沒法訪問;
        - 第三級是客戶端本地預埋的靜態通告文案,內容會比較模糊和陳舊,僅做不時之需;
  • e. 支持異步任務的雲端可配可控,好比下載類APP的下載時間、下載標的和下載條件約束(磁盤空間、移動設備電量、網絡類型等)的差別化配置,經過錯峯調度,達到削峯平谷並提高用戶體驗的效果。


特別須要注意的是,客戶端數據報告必定要有數據篩選控制和信息過濾機制,涉及用戶隱私的敏感信息和使用記錄必須杜絕採樣上報。在咱們的日誌染色機制中要特別注意,爲了排查問題很可能把關鍵、敏感信息記錄報告到後端,引入安全風險。

六、優化方法四:「多異步」


通過前面不懈的努力,初步打造了一個比較好的技術根基,好馬配好鞍,好車配風帆,怎麼就把領先優點拱手送與特斯拉了。

用戶欲壑難平,資源供不該求,靠「術」並沒有法優雅的解決。跳出來從產品角度去觀察,還有些什麼可以觸動咱們思考的深度呢。根據不一樣的需求和使用場景,用有損服務的價值觀去權衡取捨,用完美的精神追求不完美,此乃道的層面。

所謂大道至簡,完美之道,不在無可添加,而在無可刪減。經過多異步和各種緩存機制,提供區分網絡、區分業務場景下的差別化服務,是咱們孜孜以求的大「道」。

下面經過一些實踐案例的總結,來探索簡潔優雅的弱聯網體驗改善之道(開始肆無忌憚的吹噓了)。

① 網絡交互能否延後

微博客戶端某個版本啓動時,從閃屏加載到timeline界面須要6秒+。這樣的體驗是沒法接受的,與用戶2秒之內的等待容忍度是背道而馳的。從技術角度去分析,很容易發現問題,諸如咱們在啓動時有10+個併發的網絡請求(由於是HTTP短連接,意味着10+個併發的網絡連接)、閃屏加載、主UI建立、本地配置加載、本地持久化數據加載至Cache等等程序行爲,優化的目標很天然就集中在網絡請求和本地配置、持久化數據加載上。

梳理併發網絡請求,能夠從如下三個方面考察:

  • 1) 哪些請求是要求實時拉取的,好比timeline & 說起 & 私信的數字、身份校驗;
  • 2) 哪些請求是能夠異步拉取的,好比timeline、用戶Profile、雲端配置、雙向收聽列表、閃屏配置、timeline分組列表、相冊tag列表等;
  • 3) 哪些請求是能夠精簡或合併的,好比timeline & 說起 & 私信的數字與身份校驗合併。


此時,取捨就很是簡單和清晰了,啓動時1~2個網絡請求足夠應對。所作的僅僅是把一些請求延後發起,這是一種異步機制。

在移動APP裏面還有大量相似的場景,好比用戶更新了APP的某個設置項或者本身Profile的某個字段,是停在界面上轉菊花等網絡交互返回後再提示結果,亦或是把界面交互立刻還給用戶,延後異步向服務器提交用戶請求,這裏面的價值取向不一樣,「快」感也便不一樣。

② 網絡內容能否預先加載

微博客戶端在timeline刷新時,用戶向上快速滑屏,到達一個邏輯分頁(好比30條微博消息)時,有兩個取捨,一是提早預加載下個分頁內容並自動拼接,給用戶無縫滑動的體驗;二是等到用戶滑動到達分頁臨界點時現場轉菊花,卡不卡看當時的網絡情況。實踐中選擇了方案一。用戶在滑動瀏覽第一個邏輯分頁時,APP就利用這個時間窗主動預先拉取下一個邏輯分頁的內容,使得用戶能享受一個順暢的「刷」的體驗。

所作的僅僅是把一個請求提早發起了,這也是一種異步機制。思考的要點是:

  • 1) 預先加載的內容是用戶預期的嗎,預先加載和自動下載之間,失之毫厘謬以千里;
  • 2) 預先加載的內容對用戶移動設備的資源(好比流量、電量等)和後端服務器的資源(好比帶寬、存儲、CPU等)消耗要作好估算和判斷,體貼和惡意之間,也就一步之遙;
  • 3) 預先加載區分輕重數據,輕數據能夠不區分網絡情況,重數據考慮僅限優質網絡下執行,最好這些策略雲端能夠控制;
  • 4) 預先經過網絡拉取加載或存儲的過程當中,不要打攪用戶的正常使用。


在移動APP中,預加載有大量的實踐,比較典型的就是升級提醒,你們都採用了先下載好升級包,再提示用戶有新版本的策略,讓你順暢到底。

③ 用戶體驗能否降級

微博客戶端在香港公共WIFI下刷新timeline老是失敗,經過後臺用戶接入請求和響應日誌分析,判斷是香港IDC到香港公共WIFI的匯接口帶寬窄、時延大,此時該如何應對。

從前面探討的TCP/IP網絡知識,能夠知道,在一個窄帶寬高時延網絡中,吞吐量BDP必然很小,也就是說單位大小的數據傳輸所需的時間會很長。若是按照一般一次下發一個邏輯分頁timeline數據的策略,那麼從服務器到客戶端傳輸,整個數據須要拆分紅多個TCP數據報文,在緩慢的傳輸過程當中,可能一個數據報文還未傳輸完成,客戶端的鏈路就已經超時了。

若是在弱網絡(須要在應用層有測速機制,相似TCP/IP的RTT機制,測速時機能夠是拉取微博消息數字時)下,把邏輯分頁的微博消息數由30調整爲5會如何,若是方案成立,用戶刷微博的體驗是否是會降低,由於滑動一屏就要作一次網絡交互,即使是配合預加載,也可能由於網絡太慢,操控太快而又見菊花。外團在香港實測了這個版本,感嘆,終於能夠刷了。

在飢渴難耐和美酒佳餚之間,彷佛還有不少不一樣層級的體驗。聊勝於無,這個詞很精準的表述了服務分層,降級取捨的重要性。思考的要點是:

  • 1) 產品的核心體驗是什麼,即用戶最在意的是什麼,在作宏觀分層設計時要充分保障核心體驗;
  • 2) 每一個產品交互界面中,什麼數據是沒法容忍短期不一致的,即什麼是用戶不能容忍的錯誤,在作微觀分層設計時要充分考慮正確性;
  • 3) 在宏觀和微觀分層的基礎上,開始設想在什麼條件下,能夠有什麼樣的降級取捨,來保障可用,保障爽快的體驗;
  • 4) 分層不宜太多太細,大部分產品和場景,3層足矣。


在移動弱網絡條件下,到處可見降級取捨的案例。好比網絡條件不佳時,下降拉取縮略圖的規格,甚至乾脆不自動拉取縮略圖等等,分層由心,降級有意。

④ 端和雲孰輕孰重

移動APP時代,絕對的輕端重雲或者輕雲重端都是不可取的,只有端雲有機的配合,才能在一個受限的網絡通道上作出更好的用戶體驗。正所謂東家之子,胖瘦有致。

好比移動網遊APP,如取向選擇輕端重雲,那麼玩家的戰鬥計算就會大量的經過網絡遞交給服務器處理並返回,卡頓屢見不鮮,操控感盡失。

好比微博客戶端,若是取向選擇重端輕雲,微博timeline全部的消息都拉取元數據(好比微博正文包括文字、各種URL、話題、標籤、@、消息的父子關係、消息中用戶profile、關係鏈等等),由客戶端實時計算拼裝,不但客戶端用戶須要消耗大量流量計算量,並且給後端服務器帶來巨大的帶寬成本和計算壓力,若是過程當中網絡情況不佳,還會很是卡頓。

經過實踐總結,端和雲孰輕孰重,取捨的關鍵是在數據計算規模可控和數據安全有保障的前提下:

  • 1) 減小網絡往復,要快;
  • 2) 減小網絡流量,要輕。


端雲有機結合,能夠很好的演繹機制與策略分離的設計思想,從而使系統具有足夠的柔韌性。

不得再也不次特別提到的一點是,緩存技術是異步化的基礎,它滲透在性能和體驗提高的方方面面,從持久化的DB、文件,到短週期的內存數據結構,從業務邏輯數據,到TCP/IP協議棧,它無所不在。緩存涉及到數據結構組織和算法效能(耗時、命中率、內存使用率等)、持久化和啓動加載、更新、淘汰、清理方案等,有機會咱們能夠展開作專題的介紹。牢記一個字,緩存是讓用戶爽到極致的利器,但千萬別留下垃圾。

提倡多異步,其實是要求團隊認真審視產品的核心能力是什麼,深刻思考和發現什麼是用戶最關心的核心體驗,把有限的資源聚焦在它們身上。經過考察用戶使用產品時的心理模型,體驗和還原用戶使用場景,用追求完美的精神探索不完美之道。

互聯網服務核心價值觀之一「不要我等」,在移動互聯網時代仍應奉爲圭臬,如何面對新的挑戰,須要更多的學習、思考、實踐和總結,這篇文章便是對過去實踐的總結,亦做爲面對將來挑戰的思考基點。

老子曰過:上士聞道,勤而行之;中士聞道,若存若亡;下士聞道,大笑之。不笑不足覺得道。求求你了,笑一個。

知易行難,故知行合一似(jiu)爲扯蛋,那麼咱們就且扯且珍惜吧。

(上篇看了嗎?沒看請戳這裏:《移動端IM開發者必讀(一):通俗易懂,理解移動網絡的「弱」和「慢」》)

附錄:更多計算機網絡方面的資料


TCP/IP詳解 - 第11章·UDP:用戶數據報協議
TCP/IP詳解 - 第17章·TCP:傳輸控制協議
TCP/IP詳解 - 第18章·TCP鏈接的創建與終止
TCP/IP詳解 - 第21章·TCP的超時與重傳
技術往事:改變世界的TCP/IP協議(珍貴多圖、手機慎點)
通俗易懂-深刻理解TCP協議(上):理論基礎
通俗易懂-深刻理解TCP協議(下):RTT、滑動窗口、擁塞處理
理論經典:TCP協議的3次握手與4次揮手過程詳解
理論聯繫實際:Wireshark抓包分析TCP 3次握手、4次揮手過程
計算機網絡通信協議關係圖(中文珍藏版)
UDP中一個包的大小最大能多大?
P2P技術詳解(一):NAT詳解——詳細原理、P2P簡介
P2P技術詳解(二):P2P中的NAT穿越(打洞)方案詳解
P2P技術詳解(三):P2P技術之STUN、TURN、ICE詳解
通俗易懂:快速理解P2P技術中的NAT穿透原理
高性能網絡編程(一):單臺服務器併發TCP鏈接數到底能夠有多少
高性能網絡編程(二):上一個10年,著名的C10K併發鏈接問題
高性能網絡編程(三):下一個10年,是時候考慮C10M併發問題了
高性能網絡編程(四):從C10K到C10M高性能網絡應用的理論探索
鮮爲人知的網絡編程(一):淺析TCP協議中的疑難雜症(上篇)
鮮爲人知的網絡編程(二):淺析TCP協議中的疑難雜症(下篇)
鮮爲人知的網絡編程(三):關閉TCP鏈接時爲何會TIME_WAIT、CLOSE_WAIT
鮮爲人知的網絡編程(四):深刻研究分析TCP的異常關閉
鮮爲人知的網絡編程(五):UDP的鏈接性和負載均衡
鮮爲人知的網絡編程(六):深刻地理解UDP協議並用好它
鮮爲人知的網絡編程(七):如何讓不可靠的UDP變的可靠?
網絡編程懶人入門(一):快速理解網絡通訊協議(上篇)
網絡編程懶人入門(二):快速理解網絡通訊協議(下篇)
網絡編程懶人入門(三):快速理解TCP協議一篇就夠
網絡編程懶人入門(四):快速理解TCP和UDP的差別
網絡編程懶人入門(五):快速理解爲何說UDP有時比TCP更有優點
技術掃盲:新一代基於UDP的低延時網絡傳輸層協議——QUIC詳解
讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享
現代移動端網絡短鏈接的優化手段總結:請求速度、弱網適應、安全保障
聊聊iOS中網絡編程長鏈接的那些事
移動端IM開發者必讀(一):通俗易懂,理解移動網絡的「弱」和「慢」
移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結
>> 更多同類文章 ……

(本文同步發佈於:http://www.52im.net/thread-1588-1-1.html

相關文章
相關標籤/搜索