Spring Cloud Gateway其他配置
TIPS
本文转载自spring cloud gateway系列教程4—其他配置 ,这其实是对官方文档的翻译。(有修改、改进、删节)。
本文探讨Spring Cloud Gateway的其他配置,主要包括:
- 如何实现TLS/SSL(HTTPS访问)
- Spring Cloud Gateway的配置
- 如何开启Access Log
- 如何实现跨域
1. TLS / SSL
Spring Cloud Gateway使用HTTPS,是和普通的Spring boot服务配置是一样的,比如:
application.yml.
server:
ssl:
enabled: true
key-alias: scg
key-store-password: scg1234
key-store: classpath:scg-keystore.p12
key-store-type: PKCS12
Spring Cloud Gateway都可以路由转给给http和HTTPS的下游后端服务,如果是路由去HTTPS后端服务,gateway像下面一样配置信任所有下游服务:
application.yml.
spring:
cloud:
gateway:
httpclient:
ssl:
useInsecureTrustManager: true
当然这种配置,线上生成环境还是不太适合的,所以gateway可以配置自己的信任的证书列表:
application.yml.
spring:
cloud:
gateway:
httpclient:
ssl:
trustedX509Certificates:
- cert1.pem
- cert2.pem
Spring Cloud Gateway如果没有配置信任证书列表,则会拿系统默认的证书库(可以通过system property的javax.net.ssl.trustStore
属性来修改系统默认证书库)。
TLS Handshake
当是用HTTPS来通讯时,http客户端就需要初始化TLS握手连接了,所以就需要配置握手连接时的超时配置:
application.yml.
spring:
cloud:
gateway:
httpclient:
ssl:
handshake-timeout-millis: 10000
close-notify-flush-timeout-millis: 3000
close-notify-read-timeout-millis: 0
2. Configuration
Spring Cloud Gateway是通过一系列的 RouteDefinitionLocator
接口配置的,接口如下:
RouteDefinitionLocator.java.
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}
默认情况下,PropertiesRouteDefinitionLocator
会通过Spring Boot的@ConfigurationProperties
机制来加载路由配置,比如下面的例子(一个使用了完整的配置,一个使用了快捷配置,前几章也大量的用了这些配置):
application.yml.
spring:
cloud:
gateway:
routes:
- id: setstatus_route
uri: http://example.org
filters:
- name: SetStatus
args:
status: 401
- id: setstatusshortcut_route
uri: http://www.google.com
filters:
- SetStatus=401
通常情况下,properties的配置就已经够用的了,但也有一些人的需求是从外部源来加载配置文件,比如数据库等,所以官方也承诺未来的版本会基于Spring Data Repositories实现Redis, MongoDB和Cassandra版本的RouteDefinitionLocator
。
2.1 Fluent Java Routes API
除了上面的配置文件配置外,也可以通过RouteLocatorBuilder
的流式API来进行java实现配置。
GatewaySampleApplication.java.
// static imports from GatewayFilters and RoutePredicates
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
return builder.routes()
.route(r -> r.host("**.abc.org").and().path("/image/png")
.filters(f ->
f.addResponseHeader("X-TestHeader", "foobar"))
.uri("http://httpbin.org:80")
)
.route(r -> r.path("/image/webp")
.filters(f ->
f.addResponseHeader("X-AnotherHeader", "baz"))
.uri("http://httpbin.org:80")
)
.route(r -> r.order(-1)
.host("**.throttle.org").and().path("/get")
.filters(f -> f.filter(throttle.apply(1,
1,
10,
TimeUnit.SECONDS)))
.uri("http://httpbin.org:80")
)
.build();
}
这种用法就可以通过实行Predicate<ServerWebExchange>
接口来定义更复杂的匹配规则,也可以用and()
、or()
和negate()
来组合不同的匹配规则,灵活性会更大一点。
2.2 DiscoveryClient Route Definition Locator
通过服务发现客户端DiscoveryClient
,gateway可以基于注册了的服务自动创建路由。 只需要配置spring.cloud.gateway.discovery.locator.enabled=true
,以及引入DiscoveryClient
的maven依赖即可,如:Netflix Eureka, Consul or Zookeeper。
Configuring Predicates and Filters For DiscoveryClient Routes
默认情况下gateway中的GatewayDiscoveryClientAutoConfiguration
以及定义了一个predicate和filter的了。 默认的predicate是配置了/serviceId/**
路径的path predicate,当然serviceId
是DiscoveryClient
里面的服务id。 默认的filter是配置了匹配参数/serviceId/(?<remaining>.*)
和替换参数/${remaining}
的rewrite path filter,目的是将serviceId从path中去除掉,因为下游是不需要的。
你也可以自定义DiscoveryClient
路由的predicate和filter,只需要设置spring.cloud.gateway.discovery.locator.predicates[x]
和spring.cloud.gateway.discovery.locator.filters[y]
即可,如下: 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}'"
3. Reactor Netty Access Logs
spring cloud gateway是没有打印access log的,但是底层的Reactor Netty是有的,在应用启动命名中增加设置-Dreactor.netty.http.server.accessLogEnabled=true
来开启。 注:因为Reactor Netty不是基于spring boot的,所以它并不会去spring boot的配置中获取上面的配置,所以只能在Java System Property中获取。
可以在常用的日志系统中配置日志的打印文件和格式,如logback的配置:
logback.xml.
<appender name="accessLog" class="ch.qos.logback.core.FileAppender">
<file>access_log.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<appender name="async" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="accessLog" />
</appender>
<logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false">
<appender-ref ref="async"/>
</logger>
4. CORS Configuration
gateway是支持CORS的配置,可以通过不同的URL规则匹配不同的CORS策略:
application.yml.
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "http://docs.spring.io"
allowedMethods:
- GET
有不熟悉CORS的,可以看一下这篇介绍 。
此外,各种跨域的姿势,个人做了一些总结:跨域访问支持(Spring Boot、Nginx、浏览器)