架構(gòu)實(shí)戰(zhàn)與性能優(yōu)化)
我不止一次被問到微服務(wù)都上了 Spring Cloud 了為什么還要回頭整合 Dubbo是不是項(xiàng)目沒得寫了硬要給自己加戲說實(shí)話這個(gè)問題在兩三年前我也問過自己直到我真正在一條日活過百萬的業(yè)務(wù)鏈路上把 OpenFeign 換成了 Dubbo才體會(huì)到這兩者根本不是替代關(guān)系而是同一份微服務(wù)治理需求下的兩種極致互補(bǔ)方案。Spring Cloud 全家桶把生態(tài)、網(wǎng)關(guān)、配置管理做得足夠優(yōu)雅但 Dubbo 在服務(wù)調(diào)用性能、集群容錯(cuò)、流量控制上確實(shí)更硬核。這篇文章我會(huì)直接以“SpringCloud 整合 Dubbo”為核心講清楚為什么整合、怎么設(shè)計(jì)架構(gòu)、如何從零搭出可運(yùn)行的項(xiàng)目以及我在實(shí)際踩坑后整理出來的排查清單。無論你是面試前臨時(shí)抱佛腳還是項(xiàng)目里真的準(zhǔn)備落地這套組合都能從這里拿走可以直接用的東西。1. 為什么要把 SpringCloud 和 Dubbo 整合在一起1.1 兩者各自擅長什么Spring Cloud 是一套微服務(wù)全棧解決方案它的核心競爭力在“治理面”。服務(wù)注冊發(fā)現(xiàn)用 Nacos 或 Eureka配置中心用 Config 或 Nacos流量入口用 Gateway服務(wù)間調(diào)用默認(rèn)走 OpenFeign Ribbon / LoadBalancer。它把微服務(wù)最常見的周邊問題全部標(biāo)準(zhǔn)化了團(tuán)隊(duì)上手快生態(tài)內(nèi)組件統(tǒng)一。Dubbo 則更專注在“調(diào)用面”。它走的是 RPC 框架路線長連接、二進(jìn)制序列化、自有協(xié)議如 Dubbo 協(xié)議、Triple 協(xié)議在性能上比 HTTP JSON 的 OpenFeign 要強(qiáng)不少。Dubbo 還內(nèi)置了完善的集群容錯(cuò)、負(fù)載均衡、服務(wù)降級(jí)、隱式傳參等能力很多功能在 Spring Cloud 體系里要么沒有要么做得很淺。很多人以為“有了 Spring Cloud 就不需要 Dubbo”這是誤解。Spring Cloud 的 HTTP 調(diào)用在低延遲高并發(fā)場景下序列化開銷和連接管理都是一個(gè)負(fù)擔(dān)而 Dubbo 雖然調(diào)用能力強(qiáng)但它不關(guān)心網(wǎng)關(guān)層、不關(guān)心配置管理、不關(guān)心流控面板而這些恰好是 Spring Cloud 的舒適區(qū)。1.2 整合后解決了什么痛點(diǎn)我在實(shí)際項(xiàng)目里最直觀的感受是三個(gè)痛點(diǎn)被解決了。第一個(gè)是性能。舊系統(tǒng)用 OpenFeign每次調(diào)用要經(jīng)過 HTTP 層JSON 序列化、連接池分配、TCP 握手雖然 Keep-Alive 能緩解在核心鏈路高峰期P99 延遲明顯偏高。切到 Dubbo 后長連接復(fù)用加 Hessian2 序列化同樣一屏數(shù)據(jù)耗時(shí)能降到原來的三分之一左右。第二個(gè)是服務(wù)治理能力。Dubbo 的集群容錯(cuò)策略非常細(xì)Failover、Failfast、Failsafe、Forking 都有成熟語義還有內(nèi)置的 AccessLog、限流、權(quán)重路由。Spring Cloud 里這些要么不存在要么需要你自己封裝。第三個(gè)是流量視角。Spring Cloud 的負(fù)載均衡策略偏靜態(tài)而 Dubbo 的條件路由、標(biāo)簽路由、同機(jī)房優(yōu)先等能力在線上排障和多環(huán)境隔離時(shí)非常實(shí)用。整合之后我用 Nacos 統(tǒng)一做注冊中心和配置中心Dubbo 負(fù)責(zé)服務(wù)間調(diào)用Spring Cloud Gateway 負(fù)責(zé)外部流量入口兩邊各干各擅長的事這套組合在我維護(hù)的系統(tǒng)里已經(jīng)穩(wěn)定跑了近兩年。2. SpringCloud 整合 Dubbo 的整體架構(gòu)設(shè)計(jì)與選型2.1 技術(shù)棧選型Nacos 是核心粘合劑整合方案里最重要的選型就是注冊中心。曾經(jīng)有人糾結(jié)用 Eureka 還是 Nacos我建議直接選 Nacos。原因很直接Eureka 2.x 基本停更而 Dubbo 3 官方把 Nacos 作為主推注冊中心之一。Nacos 同時(shí)支持注冊中心和配置中心省掉一套獨(dú)立組件運(yùn)維上少養(yǎng)一個(gè)服務(wù)。版本選型上要注意對(duì)應(yīng)關(guān)系Spring Boot 2.3.x 對(duì)應(yīng) Spring Cloud Hoxton.SR12 與 Spring Cloud Alibaba 2.2.xNacos Client 版本建議用 2.x 系列。這套組合相對(duì)成熟穩(wěn)定網(wǎng)上踩坑案例也最齊。如果你非要上 Spring Boot 3.x那就要連 Dubbo 3.2 和 Spring Cloud Alibaba 2022.x 一起升級(jí)但至少我建議項(xiàng)目初期別碰坑太深。2.2 三級(jí)架構(gòu)網(wǎng)關(guān)、消費(fèi)者、提供者我把這套整合架構(gòu)拆成三層實(shí)際部署時(shí)也按這個(gè)分層管理接入層Spring Cloud Gateway負(fù)責(zé)外部 HTTP 請求的接入、鑒權(quán)、路由。Gateway 不直接調(diào) Dubbo它調(diào)用下游消費(fèi)者服務(wù)的 HTTP 接口。消費(fèi)層Spring Cloud 應(yīng)用網(wǎng)關(guān)的下一跳但它內(nèi)部通過 Dubbo 的DubboReference去調(diào)遠(yuǎn)端服務(wù)。提供層純 Dubbo 服務(wù)只暴露 RPC 端口不關(guān)心 HTTP 語義。這套分層的關(guān)鍵是對(duì)外統(tǒng)一 HTTP對(duì)內(nèi)統(tǒng)一 Dubbo。這樣既保證了前端接入的標(biāo)準(zhǔn)化又保證了服務(wù)間調(diào)用的高性能。2.3 為什么不建議用 OpenFeign Dubbo 雙調(diào)用并存有的團(tuán)隊(duì)會(huì)在整合初期保留 OpenFeign說萬一 Dubbo 出問題可以隨時(shí)回滾。我的觀點(diǎn)很明確如果技術(shù)上已經(jīng)決定引入 Dubbo就應(yīng)該徹底替換 OpenFeign不要兩條腿走路。雙調(diào)用并存意味著每套接口都要維護(hù)兩套客戶端而且容易發(fā)生部分服務(wù)走 Feign、部分走 Dubbo 的混亂狀態(tài)鏈路追蹤和排障復(fù)雜度會(huì)翻倍。真要穩(wěn)妥可以按服務(wù)維度灰度遷移先遷兩三個(gè)邊緣服務(wù)壓測通過后再全部切換。這不影響架構(gòu)的最終形態(tài)但能大幅降低上線風(fēng)險(xiǎn)。3. 從零搭建 SpringCloud 整合 Dubbo 項(xiàng)目3.1 創(chuàng)建父工程與依賴管理我先建一個(gè) Maven 父工程統(tǒng)一管理版本號(hào)。這里放一份最精簡的依賴配置適合直接抄作業(yè)。dependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-dependencies/artifactId version2.3.12.RELEASE/version typepom/type scopeimport/scope /dependency dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-dependencies/artifactId versionHoxton.SR12/version typepom/type scopeimport/scope /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-alibaba-dependencies/artifactId version2.2.6.RELEASE/version typepom/type scopeimport/scope /dependency dependency groupIdorg.apache.dubbo/groupId artifactIddubbo-bom/artifactId version3.0.7/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement這里有個(gè)細(xì)節(jié)要注意Dubbo 的版本不是隨便配的。Dubbo 3.0.x 有很多接口和工具類跟 2.7.x 的路徑不同如果你搜到一篇老文章寫的是com.alibaba.dubbo包名那個(gè)是舊版 Dubbo千萬別導(dǎo)入到新項(xiàng)目里。正確包名是org.apache.dubbo。3.2 服務(wù)提供者工程搭建創(chuàng)建一個(gè)獨(dú)立的 provider 模塊pom 里引入 spring-cloud-starter 基礎(chǔ)依賴和 dubbo 相關(guān) starter。dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency dependency groupIdorg.apache.dubbo/groupId artifactIddubbo-spring-boot-starter/artifactId version3.0.7/version /dependency /dependencies這里要注意provider 既需要注冊到 Nacos又需要暴露 Dubbo 服務(wù)所以spring-cloud-starter-alibaba-nacos-discovery和dubbo-spring-boot-starter必須同時(shí)存在。我見過有人只在 provider 里引入 Dubbo starter結(jié)果應(yīng)用啟動(dòng)后 Nacos 上根本看不到服務(wù)實(shí)例排查半天才發(fā)現(xiàn)少了一個(gè)依賴。配置文件 application.yml 里這樣寫server: port: 8081 spring: application: name: demo-provider cloud: nacos: discovery: server-addr: 127.0.0.1:8848 dubbo: application: name: demo-provider protocol: name: dubbo port: -1 registry: address: nacos://127.0.0.1:8848 scan: base-packages: com.example.provider.serviceprotocol.port: -1表示隨機(jī)選端口適合本地多實(shí)例調(diào)試。指定固定端口的話要注意端口沖突尤其在本地跑多套服務(wù)時(shí)。服務(wù)接口和實(shí)現(xiàn)類public interface UserService { User getUserById(Long id); }import org.apache.dubbo.config.annotation.DubboService; import org.springframework.stereotype.Service; DubboService Service public class UserServiceImpl implements UserService { Override public User getUserById(Long id) { User user new User(); user.setId(id); user.setName(user- id); return user; } }DubboService是 Dubbo 3 的注解作用是聲明這個(gè) Bean 同時(shí)被 Spring 管理和 Dubbo 服務(wù)暴露。老版本有人用Service來自 Dubbo這個(gè)在 Dubbo 3 里已經(jīng)廢棄了不要再混淆。3.3 服務(wù)消費(fèi)者工程搭建消費(fèi)者模塊的 pom 和 provider 基本一致但需要額外引入一個(gè) api 模塊。這里強(qiáng)烈建議把接口下沉到獨(dú)立的 api 模塊中provider 和 consumer 都依賴它。這樣避免了接口類重復(fù)定義導(dǎo)致的序列化類型不一致問題。消費(fèi)者里通過DubboReference注入遠(yuǎn)程接口import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; RestController public class UserController { DubboReference private UserService userService; GetMapping(/user) public User getUser(Long id) { return userService.getUserById(id); } }這個(gè)DubboReference默認(rèn)會(huì)做幾件事從注冊中心訂閱服務(wù)地址、建立長連接、配置負(fù)載均衡策略。它很像 Spring 的Autowired但它在注入的是一個(gè)遠(yuǎn)程代理對(duì)象內(nèi)部已經(jīng)幫你處理好了網(wǎng)絡(luò)通信。消費(fèi)者啟動(dòng)后你可以在 Nacos 控制臺(tái)的服務(wù)列表里同時(shí)看到 provider 和 consumer 兩個(gè)服務(wù)。這里有個(gè)容易誤導(dǎo)的點(diǎn)consumer 其實(shí)不一定要注冊到注冊中心但 Spring Cloud Alibaba 的 starter 默認(rèn)會(huì)注冊無傷大雅。真在意服務(wù)列表干凈可以在 consumer 的配置里把 Nacos 注冊關(guān)掉只留訂閱。3.4 代碼工程結(jié)構(gòu)建議我按這套方案搭了一遍最終項(xiàng)目結(jié)構(gòu)是這樣的springcloud-dubbo-demo ├── api │ └── UserService.java ├── provider │ ├── UserServiceImpl.java │ └── application.yml ├── consumer │ ├── UserController.java │ └── application.yml └── gateway ├── GatewayConfig.java └── application.ymlapi 模塊純 Java 項(xiàng)目不打 Spring Boot 的 fat jar就放接口和模型類。provider、consumer、gateway 都是獨(dú)立的 Spring Boot 應(yīng)用。3.5 網(wǎng)關(guān)層適配Gateway 在整合方案里其實(shí)是最容易踩坑的地方。我一開始以為 Gateway 能直接調(diào) Dubbo 服務(wù)后來發(fā)現(xiàn)它默認(rèn)只轉(zhuǎn)發(fā) HTTP。實(shí)際方案是讓 Gateway 轉(zhuǎn)發(fā)到消費(fèi)者服務(wù)的 REST 接口由消費(fèi)者內(nèi)部走 Dubbo。你可以在 Gateway 的 application.yml 里這樣配置路由spring: cloud: gateway: routes: - id: user-route uri: lb://demo-consumer predicates: - Path/api/user/** filters: - StripPrefix1這種方案好處很明顯網(wǎng)關(guān)層不需要感知 Dubbo 細(xì)節(jié)只負(fù)責(zé) HTTP 路由和鑒權(quán)。缺點(diǎn)是多了一層跳轉(zhuǎn)但多這層對(duì)整體性能影響微乎其微畢竟內(nèi)部走 Dubbo 的高性能已經(jīng)把跳轉(zhuǎn)開銷攤薄了。如果你非要讓 Gateway 直接調(diào) Dubbo也有變通辦法通過自定義 GlobalFilter 獲取 Dubbo 服務(wù)上下文然后手動(dòng)調(diào)用 Reference 代理。但我不推薦這會(huì)把網(wǎng)關(guān)邏輯和業(yè)務(wù)耦合得很緊密維護(hù)成本會(huì)很高。4. 整合過程中的核心配置與實(shí)現(xiàn)原理4.1 Nacos 注冊發(fā)現(xiàn)是怎么打通 Dubbo 的Dubbo 的 registry 配置nacos://127.0.0.1:8848背后做的事是Dubbo 啟動(dòng)時(shí)把自己暴露的接口和服務(wù)實(shí)例信息寫到 Nacos 的注冊列表里消費(fèi)者啟動(dòng)時(shí)從同一個(gè) Nacos 讀取服務(wù)提供者列表并建立長連接。Nacos 在這里承擔(dān)的是“通訊錄”角色它告訴你“誰在線”、“在哪臺(tái)機(jī)器上”但真正的話務(wù)是 Dubbo 直連建立的不經(jīng)過 Nacos。這就解釋了為什么 Nacos 掛了短時(shí)間服務(wù)還能繼續(xù)調(diào)用——連接已經(jīng)建立通信不依賴 Nacos。了解了這個(gè)原理你就能理解為什么建議注冊中心用集群模式部署了。注冊中心一旦徹底不可用新節(jié)點(diǎn)無法注冊消費(fèi)者新的服務(wù)發(fā)現(xiàn)也會(huì)失敗已建立的連接雖然能撐一會(huì)兒但新鮮血液進(jìn)不來最終還是會(huì)出問題。4.2 Dubbo 協(xié)議選型dubbo 協(xié)議還是 triple 協(xié)議我項(xiàng)目里用的是默認(rèn)的 dubbo 協(xié)議端口分配策略是隨機(jī)。Dubbo 3 還提供了 triple 協(xié)議它是基于 HTTP/2 Protobuf 的兼容了 gRPC 的生態(tài)。如果你的服務(wù)要跨語言調(diào)用比如 Java 和 Go 各有一套服務(wù)triple 會(huì)更合適。如果全是 Java 服務(wù)我個(gè)人建議先用默認(rèn) dubbo 協(xié)議穩(wěn)定、性能好、文檔多。triple 雖然新但 Protobuf 的 IDL 管理和接入成本要高不少團(tuán)隊(duì)如果不是想順帶搞跨語言沒必要折騰。4.3 負(fù)載均衡策略選型Dubbo 提供了多種負(fù)載均衡策略在消費(fèi)者端可以通過注解或配置指定。我常年在生產(chǎn)環(huán)境用的是random加權(quán)隨機(jī)和roundrobin加權(quán)輪詢。短連接場景下隨機(jī)策略的流量分布最平滑輪詢策略適合請求量比較均衡的場景。如果你想配置可以在消費(fèi)者的 yml 里加dubbo: consumer: loadbalance: roundrobin timeout: 3000 retries: 2timeout是單次調(diào)用的超時(shí)時(shí)間retries是失敗重試次數(shù)。這里有個(gè)大坑retries的語義是“重試次數(shù)”不是“總調(diào)用次數(shù)”。如果配置 retries2最多會(huì)嘗試 3 次。對(duì)于非冪等寫操作重試會(huì)導(dǎo)致重復(fù)下單、重復(fù)扣款。我的建議是讀接口可以配 retries1 或 2寫接口直接配 retries0。4.4 本地存根與隱式傳參Dubbo 還支持本地存根Stub就是調(diào)用遠(yuǎn)程前先在本地執(zhí)行一段邏輯。我做權(quán)限校驗(yàn)時(shí)用過這個(gè)可以先做本地?cái)r截?cái)r截掉再走遠(yuǎn)程。Stub 類需要有一個(gè)構(gòu)造函數(shù)接收遠(yuǎn)程接口實(shí)例。public class UserServiceStub implements UserService { private final UserService userService; public UserServiceStub(UserService userService) { this.userService userService; } Override public User getUserById(Long id) { if (id null || id 0) { return null; } return userService.getUserById(id); } }在DubboReference(stub com.example.consumer.stub.UserServiceStub)里指定 stub 類即可。這個(gè)小功能很實(shí)用可以讓公共校驗(yàn)邏輯在消費(fèi)端先跑一遍節(jié)省不必要的網(wǎng)絡(luò)請求。Dubbo 的RpcContext也能傳遞附加參數(shù)比如 traceId。我在整合項(xiàng)目的鏈路追蹤里就是用它把 traceId 從消費(fèi)者傳到提供者。RpcContext.getContext().setAttachment(traceId, traceId);提供者在方法里通過RpcContext.getServerContext().getAttachment(traceId)取。這個(gè)在 Dubbo 3 里 API 有變化注意用的是getServerContext()而不是老版本的getContext()。5. 實(shí)戰(zhàn)中遇到的常見問題與排查技巧5.1 服務(wù)啟動(dòng)成功但消費(fèi)端報(bào)“No provider available”這個(gè)問題幾乎每個(gè)整合 Dubbo 的人都會(huì)遇到。排查步驟按這個(gè)順序來在 Nacos 控制臺(tái)確認(rèn) provider 是否注冊成功。如果服務(wù)列表里根本沒有 provider說明 provider 的 Dubbo 配置沒生效或注冊中心地址不對(duì)。確認(rèn)接口類是不是同一個(gè)包名和類名。Dubbo 是按接口類全限定名做匹配的provider 和 consumer 都依賴同一個(gè) api 模塊才能保證完全一致。檢查消費(fèi)者配置的 registry 地址是否和 provider 相同尤其是 Nacos 的 namespace 和 group。這兩個(gè)參數(shù)不一致會(huì)導(dǎo)致服務(wù)雖然在同一集群但互相發(fā)現(xiàn)不到。查看 provider 的啟動(dòng)日志里是否輸出了Export dubbo service之類的關(guān)鍵字。如果輸出是Export ... to registry但沒有指定協(xié)議端口也可能是注冊過程出問題了。5.2 版本兼容性問題匯總我把三套主流版本組合整理成一張表方便直接對(duì)照Spring BootSpring CloudSpring Cloud AlibabaDubbo我的建議2.3.xHoxton.SR122.2.63.0.7生產(chǎn)可用推薦2.6.x2021.0.x2021.0.4.03.0.7兼容有點(diǎn)麻煩謹(jǐn)慎3.0.x2022.0.x2022.0.0.03.2.x新項(xiàng)目可試但坑多spring-cloud-starter-alibaba-nacos-discovery2.2.6 里有一個(gè)已知的坑它帶的 Nacos Client 是 1.4.2而 Nacos Server 2.x 在默認(rèn)鑒權(quán)開啟時(shí)會(huì)注冊失敗。如果你在本地測試時(shí)發(fā)現(xiàn)注冊沒問題、遠(yuǎn)程卻失敗大概率是 Nacos Server 開啟了鑒權(quán)而 Client 沒配認(rèn)證信息。解決方式是用 1.4.2 的 client 配賬號(hào)密碼或者把 starter 里的 Nacos client 版本強(qiáng)行升級(jí)到 2.x。5.3 序列化失敗與字段丟失Dubbo 默認(rèn)序列化協(xié)議下如果傳輸對(duì)象沒有實(shí)現(xiàn)Serializable接口運(yùn)行時(shí)會(huì)直接報(bào)錯(cuò)。我在項(xiàng)目里曾經(jīng)有個(gè) DTO 漏加了Serializable本地測試一切正常因?yàn)楸镜氐?JVM 序列化兜底了但上了多節(jié)點(diǎn)環(huán)境立刻出問題。另外升級(jí) Dubbo 版本時(shí)如果傳輸對(duì)象新增了字段老消費(fèi)者反序列化時(shí)會(huì)出問題。我踩過一次兩個(gè)服務(wù)同時(shí)升級(jí) Dubbo結(jié)果 2.7 版本和 3.0 版本的 Hessian2 序列化在某些字段上有兼容性差異導(dǎo)致調(diào)用鏈上數(shù)據(jù)錯(cuò)亂。所以升級(jí) Dubbo 版本時(shí)一定要所有節(jié)點(diǎn)統(tǒng)一升級(jí)別混跑。5.4 集成 Gateway 后請求超時(shí)或路由失敗GateWay 默認(rèn)轉(zhuǎn)發(fā)到下游服務(wù)時(shí)如果下游處理時(shí)間較長會(huì)出現(xiàn)網(wǎng)關(guān)層 500 或超時(shí)。我們項(xiàng)目的經(jīng)驗(yàn)是給 Gateway 配置一個(gè)較大的超時(shí)時(shí)間然后在下游 Dubbo 調(diào)用時(shí)也配置 3 秒的超時(shí)兜底。網(wǎng)關(guān)層的超時(shí)和 Dubbo 的超時(shí)是兩層概念不要混淆。網(wǎng)關(guān)超時(shí)是 HTTP 轉(zhuǎn)發(fā)層的Dubbo 超時(shí)是 RPC 調(diào)用層的。客戶端請求到網(wǎng)關(guān)網(wǎng)關(guān)再到消費(fèi)者消費(fèi)者再調(diào) Dubbo。整個(gè)鏈路超時(shí)建議按“網(wǎng)關(guān) 5 秒、Dubbo 3 秒”來設(shè)保證 Gateway 在前端超時(shí)之前有充足時(shí)間拿到結(jié)果。6. 面試題視角的整合重點(diǎn)梳理6.1 為什么選擇 Dubbo 而不是 OpenFeign這個(gè)問題是 SpringCloud 面試題里最高頻的一個(gè)。從我的實(shí)踐看可以圍繞四點(diǎn)回答性能差異RPC 長連接二進(jìn)制序列化 vs HTTPJSON、集群容錯(cuò)策略豐富度Failover、Failfast、Forking、自帶治理能力限流、降級(jí)、路由、權(quán)重、以及與 Nacos 的深度集成。不要只講“Dubbo 性能好”要給出對(duì)比場景。比如在 CPU 密集型接口里HTTP 序列化開銷對(duì)延遲影響很大而對(duì)低頻管理類接口OpenFeign 和 Dubbo 的實(shí)際差異幾乎無感。能說出“分場景選擇”才是資深水平。6.2 Nacos 在整合方案里扮演了哪些角色Nacos 是雙重身份既是注冊中心又是配置中心。在 SpringCloud 整合 Dubbo 的場景中它還負(fù)責(zé)統(tǒng)一管理服務(wù)實(shí)例元數(shù)據(jù)。你可以把 Nacos 看作整個(gè)微服務(wù)的“通訊簿配置下發(fā)通道”二合一。Nacos 作為注冊中心時(shí)Dubbo 的實(shí)例注冊和 Spring Cloud 的服務(wù)注冊共用同一套服務(wù)列表這是整合的基礎(chǔ)。但如果想隔離 dubbo 服務(wù)和 spring cloud 服務(wù)可以給 Dubbo 的 registry 配置單獨(dú)的 namespace避免兩套服務(wù)互相干擾。這個(gè)做法在公共測試環(huán)境里尤其好用。6.3 跨環(huán)境聯(lián)調(diào)怎么保證隔離我們用的是 Nacos 的 namespace 和 group 組合拳。比如開發(fā)環(huán)境用 namespacedev測試環(huán)境用 namespacetest。每個(gè) Dubbo 服務(wù)的 registry 地址配置里顯式指定 group 為DEFAULT_GROUP不行因?yàn)椴煌?xiàng)目的 group 會(huì)互相串服務(wù)。我建議每個(gè)團(tuán)隊(duì)維護(hù)一個(gè)獨(dú)立 namespace避免公共環(huán)境上服務(wù)互相污染。Dubbo 的路由功能也可以做灰度。通過Application名稱和 路由標(biāo)簽可以將特定流量路由到指定機(jī)器。比如舊版本服務(wù)帶上version1.0.0新版本帶上version2.0.0消費(fèi)者引用時(shí)指定版本就能實(shí)現(xiàn)平滑升級(jí)和灰度驗(yàn)證。7. 我的一些實(shí)操心得與后續(xù)擴(kuò)展想法先把最重要的心得放在前面整合 SpringCloud 和 Dubbo 這事的核心不是代碼而是版本對(duì)齊。我見過太多人在這一步卡住最后發(fā)現(xiàn)是 Spring Cloud Alibaba 和 Dubbo 的 starter 版本不匹配。如果你第一次做建議先把版本完全按官方推薦的一套組合跑起來跑通后再考慮升級(jí)。個(gè)人實(shí)際使用中的另一點(diǎn)體會(huì)是Dubbo 的控制臺(tái)和監(jiān)控體系比 Spring Cloud 原生方案成熟。接入 Prometheus 后Dubbo 的 Metrics 能直接提供接口維度的 QPS、響應(yīng)時(shí)間、失敗率這些數(shù)據(jù)在 Spring Cloud 里通常要做不少定制才有。這套整合方案讓監(jiān)控?cái)?shù)據(jù)收集省了很多人力。這個(gè)內(nèi)容后續(xù)還可以擴(kuò)展的方向有兩個(gè)一個(gè)是給整合方案接 SkyWalking 做鏈路追蹤把 HTTP 網(wǎng)關(guān)入口、Dubbo RPC 調(diào)用串成一條完整鏈路另一個(gè)是研究 Dubbo 3 的 Triple 協(xié)議對(duì)跨語言服務(wù)的支持。如果團(tuán)隊(duì)有 Go 和 Java 混合微服務(wù)的趨勢Triple 協(xié)議是值得提前鋪路的技術(shù)選型。最后再說一個(gè)小技巧調(diào)試的時(shí)候不要只在本地跑一個(gè) provider 和 consumer試試開多個(gè) provider 實(shí)例然后在 consumer 端把日志調(diào)整成 DEBUG 級(jí)別。你會(huì)發(fā)現(xiàn) Dubbo 的日志里能看到它選擇了哪臺(tái)機(jī)器、走了哪個(gè)負(fù)載均衡策略、耗時(shí)多少。信息量非常大比你自己猜和瞎試強(qiáng)得多。