近萬服務實例穩定運行0故障,攜程微服務框架實踐及思考

攜程從.Net技術棧的時代就已經開始微服務領域的探索,轉入Java技術棧之後,先是自研微服務框架,然後是高性能的Dubbo。目前我們正在Service Mesh的道路上探索,希望接下來能夠實現微服務框架的全面標準化以及雲原生。

一、過去(自研服務框架)

攜程在.Net技術棧時代,開始是基於ESB總線,雖然解決了內網服務調用的治理問題,但是集中式的服務架構,經常會出現單個服務把整個總線拖垮,進而導致全網癱瘓的現象。基於註冊中心的SOA服務架構,通過分佈式的服務調用,解決了單點故障帶來的巨大影響。

目前,攜程主要是以Java技術棧爲主,考慮到兼容歷史.Net技術棧,現在的框架以自研爲主,但是對比開源的高性能服務框架,自研的框架可能又存在下述提到的幾個問題。

二、現在(CDubbo服務框架)

CDubbo名字裏的C代表攜程的治理,Dubbo代表阿里開源的Dubbo SDK。縱觀過去兩年的實踐和探索,從2018年4月的第一個版本落地,到現在的近萬服務實例,我們大致可以總結爲下面的幾個主要里程碑。

2.1 註冊發現

註冊發現是分佈式服務框架的核心要素,爲了支持現有的服務互通,所以需要接入攜程的註冊中心。

服務註冊支持健康檢測擴展機制,業務可以根據業務場景自定義健康檢測擴展,例如當依賴的數據庫不可用時不再對外提供服務。服務端通過5s一次的心跳保持服務的可用性,當連續N次沒有發送心跳時就會自動通知客戶端。

客戶端發起對服務的訂閱,通過推拉結合的模式,保證節點在客戶端的最終一致性。通過Dubbo的擴展機制,實現了自定義的路由策略,比如根據方法名指定路由策略,以及根據請求參數決定不同的路由策略,同時也能夠支持就近訪問,優先訪問本機房的服務。

2.2 監控-CAT

對微服務來說,沒有了監控就好比瞎子一樣,什麼也不清楚。CAT提供了分佈式鏈路追蹤的能力,可以提供很好的報表,以及場景化的問題分析。

有時,需要了解服務總的請求量以及單機的請求分佈和QPS,或者還要知道服務的執行耗時及99線。CAT的聚合報表可以幫助我們更好的瞭解服務的健康狀況。

對於超時,可能需要知道哪個階段變慢,客戶端還是服務端,序列化階段還是服務執行過程太慢。對於異常報錯,可以看到哪個過程出現的異常,同時會打印異常堆棧信息,幫助問題的定位。

2.3 監控-Metrics

框架人員需要了解公司服務的宏觀情況,比如各機房都有哪些服務,哪些服務使用了protobuf序列化格式,哪些服務使用了SOA協議等,以及平均執行耗時等情況。業務同事可能也想知道自己服務具體情況,比如有哪些調用方,線程池是否已經跑滿了。

通過接入攜程的Dashboard,可以提供全局的總量、錯誤量、線程池統計信息,也可以根據機房、協議、序列化格式等聚合數據。還能夠自定義告警規則,在問題發生時能夠儘早的介入。

2.4 動態配置

對業務同事來說,有可能會存在依賴的服務突然變慢導致客戶端超時的情況。框架人員可能需要在機房故障時,需要全局調整check爲false,以解決A B 服務循環依賴誰都無法啓動的問題。動態配置提供了配置熱生效的能力,不需要爲了一個配置重新發布,成本很高。

服務端的多個方法,可能執行耗時也會有所不同,通過多級別的參數配置,可以設置服務默認超時爲1s,單獨爲執行較慢的方法設置獨立的超時時間爲5s。

服務Owner可能更清楚自己服務的耗時,通過服務端對客戶端的參數設置,不需要每個調用方都設置一次超時,設置的時間也會更合理一些。爲了避免配置出錯帶來的損失,我們提供了友好的可視化界面。

2.5 SOA協議及互通

爲了支持現有客戶端遷移到CDubbo,需要考慮支持現有的SOA協議。除了要確保兼容HTTP 1.1協議不變,其次要保證跟客戶端的序列化器一致。

CDubbo會通過Tomcat端口接收SOA協議的請求,利用現有的序列化器執行請求對象的轉換,並保證Dubbo內部調用和Filter鏈路的一致性,確保業務邏輯的統一,也就是業務代碼不需要改動,就可以啓動兩個協議。

2.6 測試平臺

對於私有的二進制協議來說,沒有現成的Postman等工具可以使用。有時,開發人員需要在本地驗證測試環境的服務,也可能要驗證本地啓動的服務端,每個開發人員都構造一個客戶端顯得成本比較高。

通過VI(github開源叫coreStone),以及利用Dubbo 2.7.3提供的元數據中心和泛化調用能力,我們實現了類似postman的調用工具。不但可以支持直連,也能夠支持本地測試,同時還可以支持protobuf序列化格式。關於protobuf序列化的測試方案,已經貢獻到dubbo社區,感興趣的同學可以自行了解。

2.7 升級Dubbo 2.7.3

關於Dubbo 2.7.3的詳細升級歷程,可以參考https://www.infoq.cn/article/kOxdaV3y9fMZ0Bzs0jb2

現在回顧下升級的最終結果如何。目前,攜程99%的服務已經跑在dubbo 2.7.3之上,迄今爲止0故障,只有一些不兼容的小問題,對於不兼容的問題也是確保了編譯時提前暴露,運行時沒有任何問題。

在發佈後,也陸續的出現了一些小的問題,比如預熱能力不生效,異常情況下不會回調onError等問題,支持服務端異步的Trace埋點等,這些問題已經在開源版本徹底修復了。

2.8 Threadless

業務同事反饋,需要把線程控制在理想的範圍之內。但是,dubbo的線程數量太多,一方面是服務級獨享線程池,當調用方依賴了10個服務,每個服務的QPS爲1,lantency可能只有10ms的情況下,由於每個服務獨立線程池,至少也需要10個線程了。如果多服務共享一個線程池,由於客戶端默認是Cached的線程池模式,那麼在這個場景下可能只要1個線程就足夠了。另一方面,對同步服務來說,dubbo 2.7.5的threadless可以省去DubboClientHandler線程,Netty IO線程直接把響應交給業務線程,從而節省了一次線程切換。

通過實踐,業務線程數量有了很大程度的下降,在高QPS以及依賴服務數量較多的情況下,甚至可以下降60-70%。

2.9 CDubbo服務體系

現有CDubbo的服務體系,同時支持Dubbo和SOA協議,對於Dubbo客戶端能夠支持TCP協議的傳輸,對於現有的SOA客戶端,能夠兼容現有的SOA協議。

同時,也能夠支持內網和外網gateway的請求,保證了多協議的配置統一,以及兼容了SOA的序列化格式。

2.10 性能表現

從協議層面來看,Dubbo協議的響應較SOA協議有所提升,平均耗時從之前的1ms降低到了0.3ms左右,當然具體提升也要根據服務的報文及請求量有所差異。

可能有些人會覺得幾毫秒的性能提升不足以掛齒,但是性能的穩定性對服務來說會很重要。我們觀察了服務流量突增3-4倍的情況下,客戶端還能保持0異常。長連接的多路複用,提供了很好的抗衝擊能力。

2.11 擴展性

微服務框架跟業務代碼耦合比較重,框架人員主要是用20%的時間解決業務80%的需求,另外20%的需求卻需要80%時間的問題,更適合留給業務自己去解決,能夠提供這個能力的唯有擴展性,dubbo無論橫向和縱向的擴展能力都很好。

通過實踐,發現業務的確在各個層級都有自己的擴展。例如:業務擴展了Router層,支持自己的路由規則,擴展了負載均衡策略,機票同事甚至擴展了Transport層換成了適合自己的傳輸協議。

2.12 生態

好的生態,可以降低開發成本,例如利用現有的開源dubbo admin,dubbo go等組件。另外,也可以降低業務的學習成本,在其他公司學習的dubbo框架,到了攜程還可以接着用,不需要重新學習私有的服務框架。技術支持也比較少,很多業務同事對dubbo框架非常熟悉。

2.13 Dubbo協議存在的問題

除了前面提到的各種優點,經過實踐發現現有的協議也存在着各種不足。除了對網關不太友好,沒有移動端的SDK等問題。現有的擴展機制,在A和B服務都擴展了cluster AOP的情況下,可能會導致擴展的相互影響,如何能夠保持擴展性又降低相互影響是值得探討和解決的問題。

三、未來(Service Mesh)

網上關於Service Mesh的意義講了很多,衆說紛紜,個人認爲可能最主要還是以下幾點。

  • 標準化意味着更低的成本,比如研發成本低,學習成本也比較低,其他公司學習的微服務框架,到攜程還可以繼續用,省去了學習和踩坑的成本。
  • 進程解耦,框架同學可能比較感興趣,中間件無法獨立升級的問題一直困擾着框架研發同學,在這個問題上,envoy可以獨立升級也是值得期待的。
  • 通過下沉,複用了雲基礎設施的一些能力,一方面,能夠更好的支持多語言,業務根據自己的場景選擇合適的語言,另一方面,通過下沉也能夠讓SDK更簡單,減少Jar依賴的兼容性問題。
  • 因爲更加標準以及下沉,能夠帶來更好的雲部署能力,業務出海時可以根據實際情況部署需要的組件,不再依賴框架全家桶了。

3.1 Service Mesh SDK

下圖是Istio官網提供的ServiceMesh架構圖,如果說istio解決了控制平面的標準化,envoy或者sofa-mosn解決了數據平面的標準化,那麼對於SDK來說,是否需要有個標準化的組件,或者是否存在適合我們的標準的SDK呢?

對於部分中小公司,沒有自己的中間件團隊,可能會選擇付費版的sofa。但是,對於攜程這樣的規模,對擴展性要求很強,同時已經存在上千dubbo服務的公司來說,我們可能更期待3.0的標準化能力。

3.2 現有協議不適合下沉

現有的SOA協議可能不太適合作爲標準協議,基於Http 1.1的文本協議,跟TCP協議相比,建連帶來的成本,很大程度上會導致長尾,影響服務的穩定性。

Dubbo協議由於對網關不太友好,同時存在着跨語言和協議穿透性等問題,envoy本身也可以理解爲單機網關代理,所以也不太適合作爲標準協議。

其次,存在的跨語言和協議穿透性問題,阿里劉軍同學有過分享,感興趣的同學可以參考:https://www.infoq.cn/article/y5HC2JjtAvMWYILmVILU

3.3 新協議

既然現有的協議都不太適合,是否可以考慮雲原生的標準協議gRPC。沒錯,從協議層面來看,這個選擇沒有問題,但是gRPC跟proto強綁定的問題,需要攜程現有的幾千個服務重寫業務邏輯代碼,這個成本可是無法被接受的。

我們對於新的協議的期待,應該是能夠基於POJO對象,同時還要符合gRPC協議規範。一方面,能夠很好的利用雲原生的基礎能力。另一方面,對於小衆語言,也可以利用現有的gRPC框架實現與主流SDK的互通。

對於新的SDK,不但要有標準的傳輸協議,同時考慮到服務框架與業務的緊密耦合,擴展性也是要保留的主要的特性,還需要考慮API的標準化,利用統一的監控組件。

3.4 總結

現在,我們實現了SDK的部分標準化。未來,我們一定會在雲原生的道路上走的更快,更穩,更標準。

作者介紹

海洋,攜程技術專家。對微服務和併發編程,以及應用性能調優等領域有較濃厚興趣。

本文轉載自公衆號攜程技術(ID:ctriptech)。

原文鏈接

近萬服務實例穩定運行0故障,攜程微服務框架實踐及思考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章