視頻地址:https://time.geekbang.org/dailylesson/detail/100033220
(給極客時間做個免費廣告:上面這個視頻來自極客時間的《每日一課》。最近一段時間開通極客時間企業賬號可以免費享受兩個月的《每日一課》服務)
這個技術視頻是介紹淘寶是如何落地全異步化技術,以及獲得的收益,還有關于自適應負載調節方面的內容。完整的 PPT 可以在這里(https://www.infoq.cn/article/P1S7UOYH-pQZWa53zSJL,文章末尾)下載。
一、內容大綱
下面是我總結的這個技術視頻的內容大綱:
- 實施全異步化改造的效果
- 全異步化改造的背景
- 全異步化的技術選型
- Reactive 技術的選型
- Reactive 技術的落地難點及解決方案
- 全異步化的延伸:負載自適應
二、具體內容
接下來大致介紹一下視頻的內容,其中會加入我的解釋、看法和思考。
1. 全異步化技術實施效果和背景
首先介紹的是淘寶在實施全異步化改造后的效果。最先看到的是 RT 的降低和 QPS 提升。全異步化在平時不會降低 RT、提高 QPS。但異步化有助于提升系統的兩大能力:Elastic 和 Resilient,前者反映了系統應對壓力的表現,后者反映了系統應對故障的表現。在大促時,系統會承受更大的壓力、遭受更多的故障。在這種情況下,全異步化的系統會表現出比傳統同步方式的系統有更低的 RT、更高的 QPS。
除了提高資源利用率和并發能力,全異步化還能實現鏈路上下游的故障隔離。
2. 全異步化技術選型和落地
如何實現全異步化?Future、Callback 都是老技術,不完美。Future 在異步方面改變有限,Callback 在編排能力方面有 Callback Hell 這樣的嚴重短板。Project Loom 愿景很美好,但距離發布還有好幾年的時間(不能說跳票,畢竟也從來沒宣布什么時候發布)。目前實現全異步化最理想的技術就是 Reactive Streams(https://www.reactive-streams.org/)。
淘寶選擇 RxJava 實現 Reactive。最大的原因我猜是 RxJava 技術出現較早。如果我現在選擇,會更傾向于 Project Reactor。畢竟最近兩年 Netflix 將很多開源技術停止了維護,所以選擇一個由成熟強大的開源社區維護的技術更有利于長遠發展。至于穩定性和普及性,這兩年隨著 Spring 5 和 Spring Boot 2 的成熟,以及整個 Spring 技術生態全面支持 Reactive,也不會是問題。
但技術選型只是第一步,落地實施 Reactive 有非常多的困難。困難分兩部分:技術和推廣。
技術難點
先說技術方面,落地 Reactive 主要有如下幾個難點:
- 中間件改造:如何是 RPC、MQ、鏈路跟蹤、數據庫等中間件支持 Reactive 技術
- 線程模型:統一管理線程設置
- 防止線程阻塞:阻塞 Reactive 核心線程非常危險
- 上下文傳遞:ThreadLocal 不再有效
這四點中,我認為以1、3、4點最關鍵。
第一點:中間件改造
目前 Spring 幫我們做了很多,如 Spring MVC、Spring Data、Spring Security 等都已支持 Reactive 技術。但是像 Dubbo、RocketMQ、MySQL 等技術對 Reactive 的成熟支持還需時日。因此,目前落地 Reactive 的項目對所采用的技術還是有所限制。
第三點:防止線程阻塞
Reactive 技術所使用的線程數一般只需要 CPU 核心數的兩倍,這也是默認配置。這樣,如果一旦這些線程被阻塞,那整個系統很快就會失去響應,后果很嚴重。所以,在采用 Reactive 技術之后,線程阻塞要徹底避免。但是這又是一件防不勝防的事情,自己的代碼尚且不容易完全避免引入阻塞,又如何避免其他人寫的組件和第三方類庫所引入的阻塞呢?
在線程阻塞檢查技術方面,主要有以下幾種:
最近 Project Reactor 提供了一個新解決方案:BlockHound 技術(https://github.com/reactor/BlockHound)。上面的表格中似乎沒有提到 BlockHound,后續我會跟進研究。
第四點:上下文傳遞
ThreadLocal 在 Java 技術中廣泛使用,緩存、事務、鏈路跟蹤,還有很多其它技術都采用了 ThreadLocal。但使用 Reactive 技術后,上下文信息就不能在 ThreadLocal 中傳遞了。這方面其實主要也是設計中間件技術的改造,但也有很多業務系統直接使用了 ThreadLocal,同樣需要改造。這部分工作成本不低。
推廣難點
技術難點主要是中間件團隊的工作,推廣部分主要是業務團隊的工作。要想推廣 Reactive 技術,首先要讓團隊從上至下認識到 Reactive 技術的好處。同時,還要讓直接參與改造的同學能從 Reactive 技術改造的工作中感到成就感。
這里我認為一個比較合適的切入點是全鏈路壓測和全鏈路故障演練。通過壓測和故障演練,我們能找到系統目前所存在的瓶頸和問題,針對這些瓶頸和問題,通過實施 Reactive 改造,讓大家看到收益。這樣可為 Reactive 技術改造鋪平道路。
思想上鋪平了道路,還有其它難點。其中最大的難點是 Reactive 技術對業務邏輯不友好。這方面在我之前的文章中有介紹。其中一個解決辦法就是引入 Kotlin Coroutine 技術。
3. 自適應負載調節
即便實施了 Reactive 技術改造,提升了系統的資源利用率和彈性,實現了上下游故障隔離,但在硬件條件不變的情況下,系統能力終歸是有限的。這便是我們為何要做全鏈路壓測的原因。在大促來臨之前,我們需要通過全鏈路壓測得知系統的瓶頸在哪里。但事事難料,大促實際流量總是很難估計準的,換言之就是不確定性。
這些不確定性綜合在一起,使得資源評估變成一個很難做好的事情。一個服務有多個接口,這些接口在大促期間流量是多少?這些接口流量的比例是多少?系統能力是多少?我應該為大促準備多少服務資源?這些服務所依賴的服務的這些情況又是如何?
上面這些問題綜合在一起,當系統和業務越來越復雜之后,便會變得不可解。所以,我們需要系統具備自適應負載的能力。
接下來視頻介紹的是如何實現負載自適應。
這里面最關鍵的是預測算法,預測算法參考了系統自動化控制相關技術,好壞可以從三個維度評估(這里照抄一下原文):
- 穩定性:有壓力時,經過一段時間,CPU 最終趨于某個值附近穩定,而不是發散的
- 準確性:處于穩定狀態時,CPU 的穩定性值與目標值的誤差越小越好
- 響應性:有壓力時,從一個穩定狀態過渡到另一個穩定狀態的抖動服務和時間越小越好
負載自適應,簡單說就是將過去容量評估的工作變為自動化、智能化,再結合系統自動伸縮、Reactive 技術的背壓、系統自動化配置等技術,使得系統對大流量活動的支持更輕松、更穩定。
如果想進一步了解負載自適應,可閱讀這篇文章:淘寶如何保障業務穩定性——諾亞(Noah)自適應流控 https://mp.weixin.qq.com/s/ePWqUiZcEy52mUHb4WbcSA。
三、后記:后續思考
阿里的這個分享可以說是干貨滿滿。From Reactive, More Than Reactive。互聯網公司在面對業務的快速變化、流量壓力的難以預測、故障的突如其來等種種挑戰時,簡單增加集群規模,配置靜態的限流熔斷,是無法滿足業務發展要求的。這就是全異步化和負載自適應的用武之地。
回到我目前所負責的工作,Reactive 技術和負載自適應這兩方面,對于前者,計劃在上半年對一個業務接口進行 Reactive 技術改造。而對于負載自適應,會進行初步的思考和探索。但因為要補的課還有很多,所以具體實施計劃尚不確定。