Spring Cloud Gateway的配置由一系列的“ RouteDefinitionLocator”接口實現類控制,此接口如下所示:
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}
默認情況下,通過Spring Boot的@ConfigurationProperties機制,Spring Cloud Gateway 使用PropertiesRouteDefinitionLocator從配置文件中加載路由的配置信息。之前的路由配置中,使用了一種快捷的配置方式,也可以指定具體的參數名,如下面的兩種配置方式效果是完全一樣的:
spring:
cloud:
gateway:
routes:
- id: setstatus_route
uri: http://example.org
filters:
- name: SetStatus
args:
status: 401
- id: setstatusshortcut_route
uri: http://example.org
filters:
- SetStatus=401
在一些網關的應用場景中,使用屬性配置的方式就可以了,但是在一些生產環境中,有一些路由配置信息可能是來自別的地方,比如數據庫。在將來的Spring Cloud Gateway版本中,也會添加一些基於數據庫的RouteDefinitionLocator實現類,比如Redis,MongoDB。
8.1 Fluent Java Routes API (使用Java 路由API 代碼添加路由配置)
在RouteLocatorBuilder中定義的一些 Fluent API,使用它可以在Java代碼中配置相關的路由信息,如下面代碼所示:
// static imports from GatewayFilters and RoutePredicates
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, AddRequestHeaderGatewayFilterFactory throttle) {
NameValueConfig requestHeader = new NameValueConfig();
requestHeader.setName("routes-a");
requestHeader.setValue("yes");
return builder.routes()
.route(r -> r.host("localhost:8080").and().path("/routes-api/a/**")
.filters(f ->{
f.addResponseHeader("X-TestHeader", "foobar");
return f.redirect(HttpStatus.MOVED_PERMANENTLY.value(), "http://www.xinyues.com");
})
.uri("http://localhost:8080").id("custom-1")
)
.route(r -> r.path("/routes-api/b/**")
.filters(f ->
f.addResponseHeader("X-AnotherHeader", "baz"))
.uri("http://localhost:8080").id("custom-2")
)
.route(r -> r.order(0)
.host("localhost:8080").and().path("/routes-api/c/**")
.filters(f -> f.filter(throttle.apply(requestHeader)))
.uri("http://localhost:8080").id("custom-3")
)
.build();
}
8.2 DiscoveryClient Route Definition Locator 使用服務發現客戶端定義路由信息
Spring Cloud Gateway可以使用服務發現客戶端接口DiscoveryClient,從服務注意中心獲取服務注冊信息,然后配置相應的路由。注意,需要在配置中添加如下配置開啟這個功能:
spring.cloud.gateway.discovery.locator.enabled=true
然后確保已引入DiscoveryClient的實現類的服務發現客戶端依賴,比如Eureka,Consul或Zookeeper。
8.2.1 Configuring Predicates and Filters For DiscoveryClient Routes 為路由信息配置斷言和過濾器
默認情況下,通過服務發現客戶端DiscoveryClient自動配置的路由信息中,只包括一個默認的Predicate和Filter。默認的Predicate是一個Path Predicate,模式是 /serviceId/**
,serviceId就是從服務發現客戶端中獲取的服務ID。默認的Filter是一個重寫路徑過濾器,它的正則表達式為:/serviceId/(?<remaining>.*)
,它的作用是將請求路徑中的serviceId去掉,變為/(?<remaining>.*)
,如果想要添加自定義的Predicate和Filters,可以這樣配置:spring.cloud.gateway.discovery.locator.predicates[x]
和spring.cloud.gateway.discovery.locator.filters[y]
,當使用這種配置方式時,不會再保留原來默認的Predicate和Filter了,如果你還需要原來的配置,需要手動添加到配置中,如下面所示:
application.properties
spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: Hystrix
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"
application.yml
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
predicates:
- name: Path
args:
pattern: "'/'+serviceId+'/test'"
filters:
- name: RedirectTo
args:
status: 301
url: "'http://www.xinyues.com'"
需要注意的是,在這些配置中,所有的配置的值都是會被Spel解析的,所以如果是字符串的話,需要使用引號。比如,application.yml中,如果配置成這樣:url: http://www.xinyues.com
會報錯的,詳細見:https://www.cnblogs.com/wgslucky/p/11743740.html
application.yml
這種配置是保留原來的默認的Predicate和Filter
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
predicates:
- name: Path
args:
pattern: "'/'+serviceId+'/**'"
filters:
- name: AddRequestHeader
args:
name: "'foo'"
value: "'bar'"
- name: RewritePath
args:
regexp: "'/' + serviceId + '/(?<remaining>.*)'"
replacement: "'/${remaining}'"
可以看到所有的字符串必須在引號的單引號內。
8.2.2 源碼實現
到這里下載源碼:https://gitee.com/wgslucky/SpringCloud
- 修改application.yml,激活discoveryclient配置文件
spring:
profiles:
active:
- discoveryclient
- 啟動spring-cloud-gateway項目
- 啟動spring-cloud-app-a項目
然后瀏覽器中輸入:http://localhost:8080/actuator/gateway/routes,可以看到已添加成功定義好到spring-cloud-app-a服務的路由信息了,如下所示:
可以看到里面有一個默認的filter和predicate。而且可以看出,在配置文件中配置的路由信息,java代碼中添加的路由配置信息,都加載到網關中,說明這三種配置路由信息的方式是可以一起使用的。