本文從客戶端的視角,分享客戶端如何協同服務端進行接口時間的優化。
Compose是什么
接口性能優化對于客戶端的同學來講涉及可能不是很多,但是接口的性能對于客戶端的體驗影響是巨大的;請求失敗、loading、無數據這幾個關鍵詞跟客戶端的同學一提,想必接口優化的意義就不用多說了吧。
一個快速而又穩定的接口,對于客戶端的用戶體驗來說是大有裨益的。本文從客戶端的視角,分享客戶端如何協同服務端進行接口時間的優化。
分析
?簡析
客戶端的一次完整的接口請求主要包括:
- 業務發起請求
- 網絡傳輸
- 服務端處理
- 數據響應后解析
- 圖層布局與渲染
那么我們來看一下通常客戶端發起一次接口請求,耗時都發生在哪些階段:
![]()
- Prepare:主要包括請求前的參數拼裝以及發送請求處理的線程切換;
:主要包括,鑒權、網絡傳輸、服務端處理、Network SDK的數據處理等。 - Data Parse:業務上的數據解析,如json解析等的操作,以及線程間的切換等耗時。
- UI Refresh:主要是視圖布局,渲染的操作。
- First Item Render:第一張卡片的渲染時間。
從上面數據上來看,客戶端的耗時主要是:
- 請求前的參數綁定過程
- 請求后數據解析
- 數據上屏的圖層布局以及渲染
- 異步請求過程中的線程不斷切換造成切換耗時
客戶端上這些操作往往在整個鏈路上占比較小,且過程優化空間較小;
然而大頭往往在這兩個方面:網絡傳輸和服務端處理。
方案
?降低ServerRT(服務端處理耗時)
通常降低服務端處理耗時,是由服務端小伙伴來優化,當然優化過程中需要端上一起協助完成,大致了解一下服務端耗時的幾種處理方案;
主要有這幾種方式:
- 接口加緩存:合理設計臨時緩存、持久緩存可以提高接口性能
- 內部接口并發請求:通常一個復雜的接口需要調用下游幾個業務的接口,如果合理的進行并發請求,將會收到很好的效果
- 異步化:如寫日志,更新緩存等不會影響接口準確性的非核心流程,可以采用異步方式進行處理,不阻塞主計算邏輯處理
- 數據批量處理:接口存在較大量計算,可以通過批量分批次(分而治之)方式來解決大量數據計算耗時問題
- sql加索引:數據庫SQL是最常見的性能瓶頸,如SQL子查詢、不合理索引設計、全表掃描、大量數據返回、大SQL等,通過監控平臺查看慢查詢SQL可立即找出影響接口性能瓶頸關鍵點
?降低網絡傳輸時間
雖然現有階段大多數用戶網絡已經很不錯了,但是還是有很多場景下,網絡耗時占比還是非常高,尤其長尾數據中,網絡耗時往往是最大的占比,所以網絡耗時的優化依然是非常重要;當然端上的小伙伴在這個階段可參與的空間也更多。
主要有哪些方式呢?
- 接口多段返回
通常一個接口承載了較多的內容的話,其內容就會無限的進行膨脹,如果將埋點,日志,反饋等非主線的數據進行多段返回的話將會有很大的收益,此方案主要結合接口組成進行分析;當然,此方案改動量也比較大,成本也比較高。
- 更換協議
大多數我們接口使用的是TCP協議,相比來說如果更換UDP協議,接口返回速度會快不少,詳細原因可以翻一下資料學習一下,這里不再多說。
目前也已經有成熟的方案,比如阿里的XQUIC,有感興趣的可以了解一下,具體的收益我這里也還在測試中。
- 縮小網絡包
為何縮小網絡包會降低網絡傳輸時間呢?
客戶端和服務端網絡通信時數據傳輸過程如下圖所示:
![]()
數據包越大,則在光纖傳輸時所需的時間就會越久,因此接收方等待數據包的時間也會更長,最終會導致應用層等待數據時間變長。
還有,由于TCP采用的滑動窗口機制來提升傳輸性能,窗口的大小受接收端處理速率和網絡擁塞情況影響,因此如果傳輸的包越小,則可以在盡量少的窗口周期完成數據的傳輸,減少響應的等待時間,反之,響應等待更長。
從上面幾個方式來看,業務客戶端能夠做的一部分其實是縮小網絡包的大小,那么我們下面介紹一下縮小網絡包研究。
收益
?縮小接口網絡數據包方案與收益
- 縮小網絡包,是否真的會對網絡的傳輸有效果呢?
我們對數據包的大小與網絡傳輸時長做了一個線下的實驗,以下是實驗的數據:
![]()
其他條件不變,我們將一頁返回數據改變后的數據;
可以看出網絡傳輸時間與數據包的大小是有著正相關的關系的。
- 減少網絡包大小有哪些措施呢?
更優的壓縮算法
不同的壓縮算法,壓縮算法是不一樣的:
![]()
圖片來源于網上大佬的圖片
但是,壓縮算法的調整需要考慮方面很多,如果僅僅是網絡時間的收益在很多場景下可能成本較高,暫未考慮。
減少返回數據個數
減少返回數據個數,服務端的同學已經在投入,但是遇到了一個問題,數據個數的減少就需要增加請求的次數,機器資源的成本就會升高,需要申請機器的資源;那就比較尷尬了,本身是優化,卻讓成本來買單。
精簡返回字段
在原有的請求數據上通過精簡字段,減少數據包的大小。這樣既能降低數據包,成本又不增高。如何做呢?下面來研究一下。
?精簡數據報文
- 做一個實驗
一個接口的分頁接口數據包大小在1.5M左右,Server使用的是gzip(best模式)的壓縮方式,我進行壓縮后的大小為106KB左右。通常其他接口數據包大小壓縮后普遍在10KB以下,所以可以看出分頁接口橫向對比來看,數據包大小是非常嚴重的。這也是為什么會選擇精簡數據報文作為優化手段一大原因。
- 分析
精簡數據報文需要根據業務的場景來看,我這里來舉一個我這邊實踐的例子:
從數據包上分析,業務A的數據占比59.8%,而且該業務數據元素字段重復率非常高,來看一下去除該業務后的數據包大小:
原始數據
精簡后
降低率
59.8%
從數據比對來看,不同的卡片有大約18處的不同,其占比:
占比 = 1 - (5350 / 17439) ≈ 0.693
那么,此時就有一個問題了,重復的數據,經過壓縮后還會占包大小嗎?
所以我就用服務端的壓縮方式對數據做了個壓縮:
原始數據
精簡后
原始數據Gzip壓縮
精簡后Gzip壓縮
降低率
59.8%
90%
95%
數據表明,針對重復字段的精簡,壓縮后依然是有效的。
![]()
壓縮后降低率依然有46.9%。
拿到這個結果后,如何做呢?
?數據查找表
將重復的業務數據在第一頁的數據中建立字段的查找表,然后通過端上進行合并操作,具體方式:
![]()
但是,與服務端的同學對方案時,發現請求的第一頁數據放置查找表,服務端不容易實現,因為數據在下游。
調整方案,將數據查找表改放置在每一頁數據中,這樣服務端更改就非常少了,實現也比較簡單。
但是數據放在每一頁,壓縮后還會有收益嗎?來看一下實驗的結果:
采用壓縮方式:gzip的壓縮方式
壓縮比:best模式(系統缺省值6)
方案1:
將負反饋數據查找表放在第一頁數據中:
![]()
優化前后:降低45KB
降低率 :1 - 61 / 106 ≈ 42.2%
方案2:
將負反饋數據查找表放置于每一頁數據的頭部:
![]()
優化前后:降低43KB
降低率 :1 - 63 / 106 ≈ 40.5%
實驗發現,查找表的數據僅僅占用2KB,優化依然有效。
?優化效果
- 精簡報文
在原有的數據包下,線下實驗,精簡字段會將數據包從106KB降低至63KB;線下的實驗可以得到接近90ms的優化;
- 縮小返回數據個數
縮小接口返回數據的個數,從50個降低至20個,數據大小大約降低63KB,網絡傳輸耗時減低107ms;
結論
- 數據包的大小對于接口的性能、響應以及失敗率都有影響
- 在一定場景下,數據中的重復字段對壓縮后數據包依然有較大的影響。
注:
- 網絡傳輸使用的是服務端的壓縮包,所以大小要看壓縮后的包大小
- 精簡報文有很多同學可能都試過,實現后發現收益很小,所以需要先衡量包的大小會不會對網絡傳輸造成影響,如果僅僅是幾KB的優化,從上面實驗可以看出,基本收益不大,如果是上百KB,收益肯定是有的。
團隊介紹
我們是大淘寶技術-用戶產品技術,團隊主要負責電商核心基礎鏈路業務和平臺的研發,包含:手機淘寶首頁、信息流、NewDetail、商品詳情、購物車、全域觸達、分享購物車、消息平臺等電商核心基礎能力及創新型業務。這里有世界一流的技術產品,有超大的電商基礎場景,有百億級別的數據、有超過百萬QPS的高并發流量,有豐富的業務場景,服務于10億級的消費者,這里有巨大的挑戰等著你的到來。
作者:馬啟超(是也)
出處:https://mp.weixin.qq.com/s/NYUuP1mG2o1E6QkVUoRjiw






