1. 程式人生 > >移動端IM開發者必讀(二):史上最全移動弱網路優化方法總結

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

1、前言

本文接上篇《移動端IM開發者必讀(一):通俗易懂,理解行動網路的“弱”和“慢”》,關於行動網路的主要特性,在上篇中已進行過詳細地闡述,本文將針對上篇中提到的特性,結合我們的實踐經驗,總結了四個方法來追求極致的“爽快”:快鏈路、輕往復、強監控、多非同步,從理論講到實踐、從技術講到產品,理論聯絡實際,舉一反三,希望給您帶來啟發。 如果您還未閱讀完上篇《移動端IM開發者必讀(一):通俗易懂,理解行動網路的“弱”和“慢”》,建議您先行讀完後再續本文。 本篇的目的,就是希望以通俗易懂的語言,幫助移動端IM開發者更好地針對性優化行動網路的各種特性,使得開發出的功能給使用者帶來更好的使用體驗。 本文乃全網同類文章中,唯一內容最全、“糞”量最重者,請做好心理準備耐心讀下去,不要辜負作者已打上石膏的雙手和用廢的鍵盤。

2、優化方法一:“快鏈路”

我們需要有一條(相對)快速、(相對)順暢、(相對)穩定的網路通道承載業務資料的傳輸,這條路的最好是傳輸快、不擁堵、頻寬大、收費少。生活中做個類比,我們計劃驅車從深圳到廣州,如果想當然走廣深高速十之八九要杯具,首先這個高速略顯破敗更像省道,路況不佳不敢提速;其次這條路上的車時常如過江之鯽,如果身材不好操控不便,根本就快不起來;最後雙向六車道雖然勉強可以接受,但收費居然比廣深沿江高速雙向八車道還貴;正確的選路方案目前看是走沿江高速,雖然可能要多跑一段里程,但是通行更暢快。 實際上,真實情況要更復雜,就如同上篇中【圖二 有線網際網路和移動網際網路網路質量差異】所示(就是下圖),漫漫征途中常常會在高速、國道、省道、田間小道上切換。

105942a0rtx9iin9uo5iul.jpg (748Ã247)

TCP/IP協議棧引數調優

純技術活,直接上建議得了,每個子項爭取能大致有個背景交待

① 控制傳輸包大小控制傳輸包的大小在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位視窗大小(見下圖),還有我們前面提到的流量控制機制和滑動視窗的概念,大幕徐徐拉開,主角紛紛粉墨登場。在正式詳細介紹之前,按照傳統,我們還是先站在豬場老闆的角度看一下,讀緩衝區就好比買家用來囤貨的臨時豬圈,如果貨到了買家使用部門來不及處理,就先在這裡臨時囤著,寫緩衝區就好比養豬場根據訂單裝好車準備發貨,如果買家說我現在可以收貨便可速度發出,有點明白了吧。

112051yzaw0rwlwdjwsdyy.png (649Ã435)

④ 調大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平臺,還存在系統服務被各種定製修改的問題。別擔心,辦法總比問題多,保持清醒。

⑥ 小心重試自動重試是導致後臺雪崩的重要因素之一。在行動網路不穩定的條件下,大量及時的重試不但不能達到預期,反而無謂的消耗移動裝置的電量甚至流量。因此,我們在重試前要有一些差異化的考慮:

  • 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能按需使用網路,不但簡化了鏈路管理,而且節省了電量和流量。④ 斷點續傳一方面,在討論鏈路管理時,我們建議了優質網路下的併發鏈路來完成同一個重資料拉取任務。這就會涉及到任務的拆分和並行執行,基礎是後臺能支援斷點續傳。另外一方面,從客戶端的角度而言,行動網路的不穩定特點,可能會造成某個重資料拉取任務突然失敗,無論是自動重試還是使用者驅動的重試,如果能從上次失效的上下文繼續任務,會有省時間、省電量和省流量的效果,想想也會覺得十分美好。

3、優化方法二:“輕往復”

“技”止此爾。強調網路互動的“少”,更應強調網路互動的“簡”。我們在一條高時延易抖動的通道上取得效率優勢的關鍵因素就是減少在其上的往復互動,最好是老死不相往來(過激),並且這些往復中交換的資料要儘量的簡潔、輕巧,輕車簡從。這個概念是不是有點像多幹多錯,少幹少錯,不幹沒錯。把我們實踐過的主要手段提出來探討:① 協議二進位制化二進位制比較緊湊,但是可讀性差,也因此形成可維護性和可擴充套件性差、調測不便的不良印象。這也造成了大量可見字符集協議的出現。計算機是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,可以學習借鑑。正所謂殊途同歸、心有靈犀、不謀而合,英雄所見略同......,說來說去,高效協議的優化思路也都在鏈路複用、推拉結合、協議精簡、包壓縮等等奇技淫巧的範疇之內。

③ 協議精簡協議精簡的目的就是減少無謂的資料傳輸,提升網路效能。俗話說“千里不捎針”,古人誠不我欺也。我們實踐總結以下三點供參考:  

  • 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、bzip2、LZO、Snappy、FastLZ等等,選擇時需要綜合考慮壓縮率、記憶體和CPU的資源消耗、壓縮速率、解壓速率等多個緯度的指標,對於行動網路和移動裝置而言,建議考慮使用gzip。另外需要注意的是,輕資料與重資料的壓縮演算法取捨有較大差異,不可一概而論;
  • 2) 壓縮和加密的先後秩序:一般而言,加密後的二進位制資料流壓縮率會低一些,建議先壓縮再加密;
  • 3) 注意一些協議元件、網路元件或資料本身是否已經做過壓縮處理,要避免重複工作,不要造成效能和效率的下降:比如一些圖片格式、視訊或APK檔案都有自己的壓縮演算法。

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

4、

優化方法三:“強監控”

可監方可控,我們在端雲之間,要形成良好的關鍵運營資料的採集、彙總和分析機制,更需要設計雲端可控的配置和指令下發機制。本篇重點討論與主題網路方面相關關鍵指標的“監”和“控”以就快接入為例來探討一下強監控能力的構建和使用:  

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

通過資料分析,結合伺服器自身的監控機制,可以做到:  

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

特別需要注意的是,客戶端資料報告一定要有資料篩選控制和資訊過濾機制,涉及使用者隱私的敏感資訊和使用記錄必須杜絕取樣上報。在我們的日誌染色機制中要特別注意,為了排查問題極可能把關鍵、敏感資訊記錄報告到後端,引入安全風險。

5、優化方法四:“多非同步”

經過前面不懈的努力,初步打造了一個比較好的技術根基,好馬配好鞍,好車配風帆,怎麼就把領先優勢拱手送與特斯拉了。使用者欲壑難平,資源供不應求,靠“術”並無法優雅的解決。跳出來從產品角度去觀察,還有些什麼能夠觸動我們思考的深度呢。根據不同的需求和使用場景,用有損服務的價值觀去權衡取捨,用完美的精神追求不完美,此乃道的層面。所謂大道至簡,完美之道,不在無可新增,而在無可刪減。通過多非同步和各類快取機制,提供區分網路、區分業務場景下的差異化服務,是我們孜孜以求的大“道”。下面通過一些實踐案例的總結,來探索簡潔優雅的弱聯網體驗改善之道(開始肆無忌憚的吹噓了)。① 網路互動可否延後微部落格戶端某個版本啟動時,從閃屏載入到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)為扯蛋,那麼我們就且扯且珍惜吧。