Dubbo想要個網關怎麼辦?試試整合Spring Cloud Gateway
一、背景
在微服務架構中 API網關 非常重要,網關作爲全局流量入口並不單單是一個反向路由,更多的是把各個邊緣服務(Web層)的各種共性需求抽取出來放在一個公共的“服務”(網關)中實現,例如安全認證、權限控制、限流熔斷、監控、跨域處理、聚合API文檔等公共功能。
在以 Dubbo 框架體系來構建的微服務架構下想要增加API網關,如果不想自研開發的情況下在目前的開源社區中幾乎沒有找到支持dubbo協議的主流網關,但是 Spring Cloud 體系下卻有兩個非常熱門的開源API網關可以選擇;本文主要介紹如何通過 Nacos
整合 Spring Cloud Gateway
與 Dubbo 服務
。
二、傳統 dubbo 架構
dubbo屬於rpc調用,所以必須提供一個web層的服務作爲http入口給客戶端調用,並在上面提供安全認證等基礎功能,而web層前面對接Nginx等反向代理用於統一入口和負載均衡。
web層一般是根據業務模塊來切分的,用於聚合某個業務模塊所依賴的各個service服務
PS:我們能否把上圖中的web層全部整合在一起成爲一個API網關呢?(不建議這樣做)
因爲這樣的web層並沒有實現 泛化調用 必須引入所有dubbo服務的api依賴,會使得網關變得非常不穩定,任何服務的接口變更都需要修改網關中的api依賴!
三、整合 Srping Cloud Gateway 網關
下面就開始聊聊直接拿熱門的 Srping Cloud Gateway
來作爲dubbo架構體系的網關是否可行,首先該API網關是屬於 Spring Cloud 體系下的組件之一,要整合dubbo的話需要解決以下問題:
- 打通註冊中心:spring cloud gateway 需要通過註冊中心發現下游服務,而 dubbo 也需要通過註冊中心實現服務的註冊與發現,如果兩者的註冊中心不能打通的話就會變成雙註冊中心架構就非常複雜了!
- 協議轉換: gateway 使用http傳輸協議調用下游服務,而dubbo服務默認使用的是tcp傳輸協議
上面提到的第一個問題“打通註冊中心”其實已經不是問題了,目前dubbo支持 Zookeeper
與 Nacos
兩個註冊中心,而 Spring Cloud 自從把 @EnableEurekaClient
改爲 @EnableDiscoveryClient
之後已經基本上支持所有主流的註冊中心了,本文將使用 Nacos
作爲註冊中心打通兩者
3.1. 方式一
把傳統dubbo架構中的 Nginx
替換爲 Spring Cloud Gateway
,並把 安全認證
等共性功能前移至網關處實現
由於web層服務本身提供的就是http接口,所以網關層無需作協議轉換,但是由於 安全認證
前移至網關了需要通過網絡隔離的手段防止被繞過網關直接請求後面的web層
3.2. 方式二
dubbo服務本身修改或添加 rest
傳輸協議的支持,這樣網關就可以通過http傳輸協議與dubbo服務通信了
rest傳輸協議:基於標準的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的簡寫)實現的REST調用支持
目前版本的dubbo已經支持dubbo、rest、rmi、hessian、http、webservice、thrift、redis等10種傳輸協議了,並且還支持同一個服務同時定義多種協議,例如配置 protocol = { "dubbo", "rest" } 則該服務同時支持 dubbo
與 rest
兩種傳輸協議
3.3. 總結
方式一對比 方式二 多了一層web服務所以多了一次網絡調用開銷,但是優點是各自的職責明確單一,web層可以作爲聚合層用於聚合多個service服務的結果經過融合加工一併返回給前端,所以這種架構下能大大減少服務的 循環依賴
四、代碼實踐
依賴環境
- lombok
- jdk 1.8
- Nacos 1.3
- Spring Boot 2.2.8.RELEASE
- Spring Cloud Hoxton.SR5
- Spring Cloud Alibaba 2.2.1.RELEASE
在根目錄的 pom.xml
中定義全局的依賴版本
<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>8</java.version> <spring-boot-dependencies.version>2.2.8.RELEASE</spring-boot-dependencies.version> <spring-cloud-dependencies.version>Hoxton.SR5</spring-cloud-dependencies.version> <spring-cloud-alibaba-dependencies.version>2.2.1.RELEASE</spring-cloud-alibaba-dependencies.version> <jaxrs.version>3.12.1.Final</jaxrs.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot-dependencies.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud-dependencies.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba-dependencies.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
4.1. 創建dubbo-api工程
分別定義兩個api接口
DubboService 使用dubbo協議的服務
public interface DubboService { String test(String param); }
RestService 使用rest協議的服務
public interface RestService { String test(String param); }
4.2. 創建web-dubbo工程
使用 方式一 整合對接網關,這裏爲了簡化在同一個服務下只使用邏輯分層定義controller層與service層,並沒有做服務拆分
4.2.1. 創建配置
定義 spring boot 配置
server: port: 8081 spring: application: name: zlt-web-dubbo main: allow-bean-definition-overriding: true cloud: nacos: server-addr: 192.168.28.130:8848 username: nacos password: nacos
server.port
:配置應用服務器暴露的端口
spring.cloud.nacos
:配置 spring cloud 的註冊中心相關參數,nacos 的配置需要改爲自己環境所對應
定義 dubbo 配置
dubbo: scan: base-packages: org.zlt.service protocols: dubbo: name: dubbo port: -1 registry: address: spring-cloud://localhost consumer: timeout: 5000 check: false retries: 0 cloud: subscribed-services:
dubbo.scan.base-packages
:指定 Dubbo 服務實現類的掃描基準包
dubbo.protocols
:服務暴露的協議配置,其中子屬性 name
爲協議名稱, port
爲協議端口( -1 表示自增端口,從 20880 開始)
dubbo.registry.address
:Dubbo 服務註冊中心配置,其中子屬性 address
的值 "spring-cloud://localhost",說明掛載到 Spring Cloud 註冊中心
4.2.2. 創建DubboService的實現類
通過 protocol = "dubbo"
指定使用 dubbo協議
定義服務
@Service(protocol = "dubbo") public class DubboServiceImpl implements DubboService { @Override public String test(String param) { return "dubbo service: " + param; } }
4.2.3. 創建Controller類
使用 Spring Boot
的 @RestController
註解定義web服務
@RestController public class WebController { @Autowired private DubboService dubboService; @GetMapping("/test/{p}") public String test(@PathVariable("p") String param) { return dubboService.test(param); } }
4.3. 創建rest-dubbo工程
使用 方式二 整合對接網關,由於該服務是通過dubbo來創建rest服務,所以並不需要使用 Spring Boot 內置應用服務
4.3.1. 創建配置
定義 spring boot 配置
spring: application: name: zlt-rest-dubbo main: allow-bean-definition-overriding: true cloud: nacos: server-addr: 192.168.28.130:8848 username: nacos password: nacos
因爲不使用 Spring Boot 內置的應用服務所以這裏並不需要指定 server.port
定義 dubbo 配置
dubbo: scan: base-packages: org.zlt.service protocols: dubbo: name: dubbo port: -1 rest: name: rest port: 8080 server: netty registry: address: spring-cloud://localhost consumer: timeout: 5000 check: false retries: 0 cloud: subscribed-services:
dubbo.protocols
:配置兩種協議,其中rest協議定義 8080 端口並使用 netty 作爲應用服務器
4.3.2. 創建RestService的實現類
通過 protocol = "rest"
指定使用 rest協議
定義服務
@Service(protocol = "rest") @Path("/") public class RestServiceImpl implements RestService { @Override @Path("test/{p}") @GET public String test(@PathParam("p") String param) { return "rest service: " + param; } }
4.4. 創建Spring Cloud Gateway工程
定義 spring boot 配置
server: port: 9900 spring: application: name: sc-gateway main: allow-bean-definition-overriding: true cloud: nacos: server-addr: 192.168.28.130:8848 username: nacos password: nacos
server.port
:定義網關端口爲 9090
定義網關配置
spring: cloud: gateway: discovery: locator: lowerCaseServiceId: true enabled: true routes: - id: web uri: lb://zlt-web-dubbo predicates: - Path=/api-web/** filters: - StripPrefix=1 - id: rest uri: lb://zlt-rest-dubbo predicates: - Path=/api-rest/** filters: - StripPrefix=1
分別定義兩個路由策略:
- 路徑
/api-web/
爲請求web-dubbo
工程 - 路徑
/api-rest/
爲請求rest-dubbo
工程
4.5. 測試
分別啓動:Nacos、sc-gateway、web-dubbo、rest-dubbo 工程,通過網關的以下兩個接口分別測試兩種整合方式
- http://127.0.0.1 :9900/api-web/test/abc :請求
web-dubbo
工程測試整合方式一 - http://127.0.0.1 :9900/api-rest/test/abc :請求
rest-dubbo
工程測試整合方式二
五、demo下載
ide需要安裝 lombok
插件
https://github.com/zlt2000/dubboSpringCloud
掃碼關注有驚喜!