一、背景
在微服務架構中 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
兩個注冊中心,而 Spring Cloud 自從把
Nacos
改為
@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 服務實作類的掃描基準包
dubbo.scan.base-packages
:服務暴露的協定配置,其中子屬性
dubbo.protocols
為協定名稱,
name
為協定端口( -1 表示自增端口,從 20880 開始)
port
:Dubbo 服務注冊中心配置,其中子屬性
dubbo.registry.address
的值 "spring-cloud://localhost",說明挂載到 Spring Cloud 注冊中心
address
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:
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:
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工程
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