介面優化策略

DreamWeaver_Zhou發表於2017-12-27

對於程式優化,我一直採取保守的態度,除非萬不得已。但是隨著業務的不斷髮展,程式越來越複雜,程式碼越寫越多,優化似乎是終有一天會到來的事情。

那麼對於一個典型的後臺服務介面,我們可以從那些方面入手進行優化呢?

介面拆分

介面垂直拆分

垂直拆分可以簡單理解為微服務化,把一個大而複雜的服務拆分成多個相互獨立,職能單一的服務,單獨部署。 更細粒度拆分的好處是,能對某個具體的微服務進行特殊優化,以最大的投入產出比來解決整個服務的效能。 垂直拆分還有一個好處是,對於非必須的介面,可以很方便的進行降級處理,把壞影響隔離到核心邏輯外部。 最容易想到的優化辦法是把某個對整體效能有決定性影響的微服務介面進行水平擴容。

  • 注意: 拆分後必定會增加外部介面呼叫,多少會有些額外開銷,但是對於有限幾個呼叫,拆分的還是值得的。

介面水平拆分

這裡說的水平拆分一定不是把一個介面部署更多份,因為這樣只能解決介面的容量問題,但是不能減少介面的響應時間。 水平拆分可以簡單理解成mapreduce模型,把整個計算邏輯或者資料平均分配到叢集中的N個伺服器去,然後由一臺機器去併發呼叫並做結果合併。 理論上這種方式能把響應減少到的時間。

  • 注意: 一個問題需要考慮的是,如果併發呼叫的介面返回的資料量比較大,可能會對合並機器的網路負載和資料序列化(CPU)有一定影響。

快取

介面快取

一個有著複雜邏輯或者大量計算資料的介面,能對整個結果進行快取再好不過了。快取針對不同的場景會有多種策略,對於有大量併發請求的場景, 推薦一個方案:一種基於“哨兵”的分散式快取設計,不會有損失第一個使用者,也不會有定時更新快取的額外開銷。

本地快取

本地快取有兩種場景,對於類似字典型別的資料,可以靜態化後放入記憶體,定時去重新整理或者採用通知機制去更新。

還有一種場景是用ThreadLocal快取重複內部計算與重複的物件建立; 對於鏈路比較長或者迴圈比較深的介面,ThreadLocal減少重複計算和物件建立,從而降低RT和節約記憶體。

  • 注意: 在有內部併發的地方使用ThreadLocal一定要注意不同執行緒間的資料同步。主執行緒的ThreadLocal資料和每個併發子執行緒的ThreadLocal資料要同步好。

內部優化

非核心流程非同步化

類似於發訊息,寫日誌,更新快取等不會影響介面準確性的非核心流程,可以採用非同步方式進行處理,不阻塞主計算邏輯處理。

內部併發

如果進行水平拆分後,併發呼叫IO較大,可以考慮換成內部併發解決IO問題。如果內部併發涉及到每個執行緒更新同一個集合資料,不用忘了使用執行緒安全的集合。 這裡有一個併發更新HashMap的case:併發環境下HashMap引起full gc排查。

相關文章