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

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

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

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

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