搜索關注微信公眾號"捉蟲大師",后端技術分享,架構設計、性能優化、原始碼閱讀、問題排查、踩坑實踐,
本文已收錄 https://github.com/lkxiaolou/lkxiaolou 歡迎star,
背景
在很久以前,網站應用是單體應用的架構,流量小,所有功能、代碼都部署在一起,成本低,此時資料庫訪問框架ORM是關鍵,
后來流量逐漸增大,單體應用被拆分為互不相干的多個應用,這就是垂直架構,此時加速前端頁面開發的Web框架MVC是關鍵,
再后來,垂直應用越來越大,應用間的互動不可避免,分布式服務框架RPC變成了關鍵,
dubbo
RPC,全稱Remote Procedure Call,即遠程程序呼叫,一句話描述就是呼叫遠程物件就像呼叫本地方法一樣方便簡單,常見的RPC框架有dubbo、grpc、thrift等,

dubbo, |?d?b??| 是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向介面的遠程方法呼叫,智能容錯和負載均衡,以及服務自動注冊和發現,目前使用dubbo的公司非常多,

前世今生
dubbo的發展歷程可以總結為3個階段:
- 誕生阿里:dubbo前生2008年在阿里內部誕生,2011年開源,2012年發布2.5.3版本后停止更新
- 當當續命:2014年當當發布dubbox,是基于阿里開源的dubbo 2.5.3版本增加rest協議的dubbo版本
- 重啟登頂apache:2017年阿里重啟dubbo專案,并于2018年進入apache范訓,2019年成為apache頂級專案,同時也發布了dubbo.js,dubbo-go等多語言dubbo版本,2020年發布3.0往云原生專案發展的戰略計劃

目前支持的版本主要是2.6.x和2.7.x:
- 2.6.x 主要以 bugfix 和少量 enhancements 為主,因此能完全保證穩定性
- 2.7.x 作為社區的主要開發版本,得到持續更新并增加了大量新 feature 和優化,同時也帶來了一些穩定性挑戰
協議
dubbo原生的協議定義如下:
- 0-15: 魔數,判斷是否是dubbo協議
- 16: 判斷是請求還是回傳
- 17: 判斷是否期望回傳
- 18: 判斷是否為事件訊息,如心跳事件
- 19-23: 序列化標志
- 24-31: 標志回應狀態(類似http status)
- 32-63: 請求id
- 64-95: 內容長度(位元組)
- 96-?: 序列化后的內容(換行符分隔)

dubbo協議的優點是設計緊湊、請求回應的header一致;缺點是無法通過header定位資源,header和body中欄位存在冗余,協議無法擴展,
當然同時也支持擴展多種協議,如當當擴展的rest協議,還有最新支持的grpc協議等
說到擴展,可能是dubbo設計的最大亮點,dubbo的擴展基于SPI(Service Provide Interface)設計,可以無侵入代碼實作非常多的功能,
注冊中心
注冊中心有如下特點:
- 動態加入,服務提供者通過注冊中心動態的把自己暴露給消費者,無需消費者逐個更新組態檔,
- 動態發現服務,消費者可以動態發現新的服務,無需重啟生效,
- 統一配置,避免本地配置導致每個服務配置不一致,
- 動態調整,注冊中心支持引數動態調整,新引數自動更新到所有相關的服務節點,
- 統一管理,依靠注冊中心資料,可以統一管理配置服務節點,dubbo主流的注冊中心一般用zookeeper或者nacos,其他還有很多擴展實作,
集群
集群包含了路由、負載均衡和集群容錯三個內容,從一個例子來看這三方面的差異:
一個dubbo的用戶服務,在北京部署了10個,在上海部署了20個,一個杭州的服務消費方發起了一次呼叫,然后發生了以下的事情:
- 根據配置的路由規則,如果杭州發起的呼叫,會路由到比較近的上海的20個provider,
- 根據配置的隨機負載均衡策略,在20個provider中隨機選擇了一個來呼叫
- 假設隨機到了第7個provider,結果呼叫第7個 provider 失敗了,根據配置的failover集群容錯模式,重試其他服務器,重試了第13個provider,呼叫成功,
這里1對應了路由,2對應了負載均衡,3對應了集群容錯,
filter
在dubbo的整體設計中,filter是一個很重要的概念,包括dubbo本身的大多數功能,都是基于此擴展點實作的,在每次的呼叫程序中,filter的攔截都會被執行,filter是一種責任鏈的設計模式:

常見的filter:監控打點、日志記錄、限流降級、鑒權等,
三大中心
三大中心指注冊中心,元資料中心,配置中心,為什么需要三大中心,可以看一條dubbo注冊到注冊中心上的資料:
/dubbo/org.apache.dubbo.demo.DemoService/providers/dubbo%3A%2F%2F172.23.234.48%3A20880%2Forg.apache.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo-api-provider%26default%3Dtrue%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.demo.DemoService%26metadata-type%3Dremote%26methods%3DsayHello%2CsayHelloAsync%26pid%3D21563%26release%3D%26side%3Dprovider%26timestamp%3D1600336623852
可以看出資料量很大,這還是介面級的資料,當介面數量越來越多,注冊中心的壓力越來越大,變更推送的資料越來越多,
所以,我們需要元資料中心和配置中心來減輕注冊中心的壓力,不經常變化的資料可以放在元資料中心,
/dubbo/org.apache.dubbo.demo.DemoService/providers/dubbo%3A%2F%2F172.23.234.48%3A20880%2Forg.apache.dubbo.demo.DemoService%3Fapplication%3Ddubbo-demo-api-provider%26deprecated%3Dfalse%26dubbo%3D2.0.2%26timestamp%3D1600336144382
配置中心也是如此,如果沒有配置中心需要全量將變更的url推送下去,有了配置中心只需要推送變更的配置即可,
泛化呼叫
我們常見的dubbo呼叫方式是引入provider定義的介面jar包,但如果沒有這個jar包,能否發起呼叫?當然是可以,也確實有這樣的場景,比如服務測驗平臺,dubbo服務網關等,只要知道介面名,引數等資訊即可發起呼叫,

未來發展
dubbo當時的未來規劃其實走了個曲線,并不是一步到現在的云原生方向,2019年想走的方向是回應式編程(或者叫反應式編程),IO密集型的應用,通常執行緒池是限制吞吐的重要因素之一,假設consumer執行緒池為100,provider介面回應時間為500ms,consumer的qps上限為 (1000 / 500) x 100 = 200,回應式編程就是解決這個問題,
回應式編程(reactive programming)是一種基于資料流(data stream)和變化傳遞(propagation of change)的宣告式(declarative)的編程范式,RSocket 是一個支持 reactive-stream 語意的開源網路通信協議,它將 reactive 語意的復雜邏輯封裝了起來,使得上層可以方便實作網路程式,Dubbo 在 3.0.0-SNAPSHOT 版本里基于 RSocket 對回應式編程提供了支持,用戶可以在請求引數和回傳值里使用Mono和Flux型別的物件,

但到了2020年,隨著云原生概念的興起和大廠紛紛地落地,dubbo是否也可以朝這個方向發展呢?
云原生是基于容器、服務網格、微服務、不可變基礎設施和宣告式API構建的可彈性擴展的應用,基于自動化技術構建具備高容錯性、易管理和便于觀察的松耦合系統,構建一個統一的開源云技術生態,能和云廠商提供的服務解耦,
dubbo的服務級注冊發現,與k8s容器編排的應用級服務發現相違背,dubbo是“重sdk”,與易管理相違背,
所以在最新的版本中支持了應用級的服務發現,原先是這樣的一個介面:
/dubbo/org.apache.dubbo.demo.DemoService/providers/dubbo%3A%2F%2F172.23.234.48%3A20880%2Forg.apache.dubbo.demo.DemoService%3Fapplication%3Ddubbo-demo-api-provider%26deprecated%3Dfalse%26dubbo%3D2.0.2%26timestamp%3D1600336144382
使用應用級服務發現注冊到注冊中心上是這樣
/services/dubbo-demo-api-provider/172.23.234.48:20880
而重sdk,未來可能會被mesh改善,據說阿里內部已經有dubbo mesh落地的業務線了,
搜索關注微信公眾號"捉蟲大師",后端技術分享,架構設計、性能優化、原始碼閱讀、問題排查、踩坑實踐,
本文已收錄 https://github.com/lkxiaolou/lkxiaolou 歡迎star,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/427413.html
標籤:Java
上一篇:Java實作AES演算法
