零。前言
這里講的移動APP主要指的是安卓平臺,大部分情況也適用于IOS等移動平臺,可能重點嘛會在后半部分呢。
一。嵌入多SDK存在的隱患
但凡一個常用的APP都會嵌入至少一個SDK,不同來源或同一來源,有廣告SDK,有推送SDK,有性能匯報SDK,有用戶跟蹤SDK,有統計流量SDK等,有支付SDK等等。雖然帶來了功能的復用和解耦,便于縱向擴展,但可能會存在:
- 一個SDK可以看做一個后臺Service,多個SDK多個Service存在(粗略上計算)
- 運行緩慢的問題,多個SDK或多功能的模塊(若不按需加載的話)會導致運行緩慢,符合木桶理論,最慢的那個拖慢了總體步伐
- 每一個SDK都有自己核心訴求,各自為政,實現方式各異。總體架構是否合適,帶來了隱形的兼容成本
- 彼此協調運作兼容性問題,一旦出現某個隱含BUG,會不會導致連鎖反應
- CPU、內存、網絡等資源競爭問題,想協調都很難
- 網絡資源各自為政,無法共享,更不用提連接復用
若是同一來源的SDK,當問題發生的時候還能夠有所協作稍作調整,雖然這也是比較理想的情況。外部的SDK可能問題反饋和BUG修正,時效性就不太好說了。
解耦雖然帶來了功能的擴展性,帶隨之帶來了資源利用方面的重復和浪費,愈多的SDK嵌入越有可能導致總體運行緩慢,需要謹慎使用。
二。APP后臺Service數量很多
一般安卓手機會提供后臺進程的查看,一般APP會啟動多個后臺服務,比如愛奇藝APP就很變態,5個服務存在(優酷APP也好不了哪去,3-4個服務存在):

一般較大公司,都會自己開發SDK,但礙于KPI等業績考核,很少有人會認真從總體上考慮把多個Serice服務合并為一個,節省一點用戶的資源占用,不過那需要考驗研發人員的架構能力了。
雖然小白用戶不一定會查看后臺服務,但若干個后臺服務,每一個都需要維護自身服務存活檢測,每一個都會占用若干內存,若合并為一個,自然減少了CPU占用和內存資源占用,以及維護成本,還是有些小必要的。
三。HTTP短連接請求過于頻繁
一般來講,打開一個APP的時候,通過Wireshark抓包工具可以看到若干個HTTP連接瞬間建立,諸如淘寶,天貓,美團,優酷等APP,滿屏的都是HTTP請求,看著讓人感覺有些小恐怖,業務數據、設備信息上傳、SDK信息抓取、埋點跟蹤、頭像圖片、HTML資源等,那叫一個龐大。
但也沒辦法,業務展示那么豐富,需要消耗過多的資源。大部分請求都只專注于一部分數據。針對單一顯示界面屏幕,可以通過一個請求獲得合并后的響應結果,減少網絡資源消耗。
手機淘寶和手機QQ,在HTTP請求優化方面,已經在使用IP直連、HTTP長連接、SPDY等進行加速處理,值得學習。
四。TCP長連接利用率不高
這里所說長連接,更多的是指TCP方式連接,也包括HTTP方式的長連接,但更多指的是具有雙向通道的長連接。單通道的方式,協議所限,資源利用率不是那么高。
當前TCP長連接在其存活期間,大都只專注于傳輸一類具體業務內容,比如PUSH推送,一臺手機連接一天,也接收不了幾條消息,最頻繁的就是心跳保活數據包傳送了。
一旦涉及到新的業務,大家都是要新建一條全新TCP連接,彼此業務不關聯嘛,看上去很耦合啊,但卻造成了企業大量的重復資源浪費:新的業務需要處理另外的連接接入,資源重復投入,業務層面嘛,也會存在一半左右的重疊。當然,若不在乎這些的話,就另當別論了,但是你要是能夠為消費者手機的資源消耗考慮,那便是用戶的福音了。

長連接的業務層面多路復用,支持類似于搖一搖、搶紅包、客服、客服咨詢等,同一個連接傳輸不同類型的數據,即節省了服務器資源,又提高了網絡連接利用率,兩端的維護成本降低。針對客戶端而言,多路業務復用在一條TCP連接上傳輸,需要業務路由 + 相應業務處理即可。服務器端嘛,接入不同的業務處理,依靠業務路由進行消息分發。
題外話,舉一個例子,平時任一時間點約3000千萬用戶連接,按每臺接200萬計算,10-20臺機器接入處理足可,推送啊,聊天啊,客服咨詢,平常再來一個好運搖一搖都行。年底了要擴容到1億左右用戶搖啊搖的搶東搶西搶紅包,還是同一個連接的方式,不過增加了新的業務類型數據傳遞,服務器嘛,擴展到50-80臺就很OK了。用戶量一旦降落,撤下多余機器就行。或許,有空可以寫一篇供一億用戶在線的系統架構的方法 :))
五。HTTP 持久連接使用
針對HTTP/1.1可能很多人的思維方式,還停留在瀏覽器環境,一般瀏覽器有不支持或支持不夠好,但在非瀏覽器環境下,針對APP應用的環境,少了很多傳統瀏覽器環境的限制,但要完全發揮和釋放HTTP/1.1協議所帶來的持久特性,這便需要深度理解協議規范和具體的使用環境等進行抉擇。
1. HTTP/1.1 KeepAlive特性使用

雖說HTTP/1.1 Keep-Alive特性支持多個請求在同一個連接上排隊發送,在瀏覽器端正常的HTML等資源請求,會帶來線頭阻塞弊端,后一個請求依賴于前一個請求完成,一旦出現阻塞,后續請求只能排隊等待。
但若針對非瀏覽器、業務模型不是很復雜的環境,比如日志采集/跟蹤等常見業務,屬于簡單循環的請求-響應模型,響應僅僅需要HTTP 200狀態碼即可(這要求服務器端接收之后異步處理直接返回200狀態),后續的請求只需要排隊,并且不會對延遲有苛刻要求,那么Keep-Alive特性就很適合。一般出現阻塞,那就意味著網絡狀況不容樂觀,關閉然后重鍵一個HTTP持久連接就行。
有些環境,只需要發送數據,客戶端不關心有沒有響應(或不接收響應),類似于UDP的方式,比如實時日志(突出實時特性),但這需要客戶端異步處理響應。
一般視頻網站都會有實時跟蹤用戶正在播放中的視頻播放狀態,那就需要建立一個持久的HTTP/1.1連接,即時、持續傳遞視頻觀看事件,自然就避免了短連接多次創建、關閉的開銷。
2. HTTP/1.1 Pipelining
建立在Keep-Alive持久化基礎之上,中文譯為管線化,支持連續的冪等的GET/HEAD方法請求,實際環境下,并沒有被瀏覽器所支持。
同一個連接,處理同樣的三次請求-響應,Keep-Alive和Pipelining方式不同:

瀏覽器環境不支持的特性,在應用環境下或許可以找到其適用空間。比如具有通過GET方式提交數據的情況(比如GET方式匯報地理位置,GET方式提交用戶設備信息,GET方式匯報用戶手機抖動情況等),多個請求批量發送。
但換一個思維方式,若能夠合并批量請求為一個POST提交,不走管線化方式,可能會更合適一些。
針對不太重要數據,發送完畢,不用等待響應。
3. HTTP/2
若想了解HTTP/2的規范,可以參考本博客的其它文字。目前客戶端庫和服務器端庫,支持都不太好,需要觀察一段時間,公司實力夠,完全可以自主開發,或基于SPDY 2.0也可,目前淘寶APP、騰訊手QQ等,也都在使用。
HTTP/1.1能夠完全解決的問題,就沒有必要使用HTTP/2,后者造成了實現有些復雜,可能中介設備(網關、代理、CDN等)都還沒有為之做好準備呢,但HTTP/2畢竟是趨勢。
雖然規范只定義一個Hostname只允許一個連接,可能實際情況下會需要2-3條長連接以爭奪較多的網絡帶寬資源。
六。小結
怎么說呢,在當前移動APP環境下:
- TCP長連接的通道用途的傳輸潛力和利用率很低
- HTTP/1.1的持久特性很容易被人忽略,未能正確使用
- HTTP/2多路復用值得期待
無論哪一種方式,都需要熟悉協議和網絡,適合的環境使用適合的協議特性,才能夠發揮出潛在的性能出來。