springGateway配置需要注意的点
1. 超时时间
springGateway使用的是WebFlux里面的WebClient来执行请求,WebClient有一些超时时间需要配置,
默认的可能不太合适。
1 2 3 4 5 6
| spring.cloud.gateway.httpclient.connect-timeout=
spring.cloud.gateway.httpclient.response-timeout=
spring.cloud.gateway.httpclient.pool.max-idle-time=
|
2.缓存时间
gateway里面难免要使用负载均衡,如果使用的是Spring-cloud-loadbalance实现,loadbalance从discover-client拿到实例信息会存入缓存,默认缓存30秒。因为discover-client本身可能也带有缓存(不同的discover-client可能不一样),所以loadbalance里的缓存没必要太长时间,此处调整成5秒
1 2 3 4
| spring.cloud.loadbalancer.cache.ttl=5s
spring.cloud.loadbalancer.ribbon.enabled=false
|
3.异常拦截返回值
默认情况下,gateway报错时会输出简单的错误json,或空白错误页面,但页面中的隐私的信息如错误堆栈会被删掉,调试阶段,可以将它开启,更多选项都在server.error.
里面
1 2 3
| server.error.whitelabel.enabled=true server.error.include-exception=true server.error.include-message=always
|
这里的控制逻辑在org.springframework.boot.web.reactive.error.DefaultErrorAttributes#getErrorAttributes(org.springframework.web.reactive.function.server.ServerRequest, org.springframework.boot.web.error.ErrorAttributeOptions)
方法里,如果没在server.error.
配置里开启的数据,都被移除了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Override public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) { Map<String, Object> errorAttributes = getErrorAttributes(request, options.isIncluded(Include.STACK_TRACE)); if (this.includeException != null) { options = options.including(Include.EXCEPTION); } if (!options.isIncluded(Include.EXCEPTION)) { errorAttributes.remove("exception"); } if (!options.isIncluded(Include.STACK_TRACE)) { errorAttributes.remove("trace"); } if (!options.isIncluded(Include.MESSAGE) && errorAttributes.get("message") != null) { errorAttributes.put("message", ""); } if (!options.isIncluded(Include.BINDING_ERRORS)) { errorAttributes.remove("errors"); } return errorAttributes; }
|
4.断路器
如果使用的Resilience4J作为断路器,一定要进行配置,因为默认的断路器超时时间是1秒,这肯定是不够的。自定义一个Customizer,将超时时间设为60秒。
1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration(proxyBeanMethods = false) public class Resilience4JConfig {
@Bean public Customizer<ReactiveResilience4JCircuitBreakerFactory> customReactiveResilience4j() { return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id) .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()) .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(60)).build()) .build()); }
}
|
需要添加的依赖是,才能使用resilience4j。
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId> </dependency>
|
5.路由顺序
生成RouteLocator是没有顺序的,不会按照最佳匹配来处理,要想让生成的RouteLocator排在前面可以使用@Order
注解,添加注解的一定优先于不加注解的,注解里面填的数字越小越优先。
1 2 3 4 5 6 7 8 9
| @Bean @Order(-1) public RouteLocator test(RouteLocatorBuilder builder) { return builder.routes() .route(ps -> ps.path("/test") .uri("lb://server") ) .build(); }
|
6.添加filter的方式
下面两种添加filter的方式有什么区别吗?
1 2 3 4 5 6 7 8 9 10 11 12 13
| public RouteLocator test(RouteLocatorBuilder builder) { return builder.routes() .route(ps -> ps.path("/aaa") .filters(sp -> sp.filter((ex, chain) -> chain.filter(ex))) .uri("lb://server") ) .route(ps -> ps.path("/bbb") .uri("lb://server") .filter((ex, chain) -> chain.filter(ex)) ) .build(); }
|
答:
一个是在执行path后,使用filters
添加,一个是在uri方法后使用filter
方法添加。既然是filter链肯定是要排序的,第一种方式添加filter会被包装成OrderFilter,排序号为0,第二种方式filter不会被包装,没有排序号。
gateway默认提供的十个globalFilter是实现Order接口的,所以第一种方式添加的filter,会插入到globalFIlter之间(具体顺序请查看每个globalFilter的顺序),第二种方式加入的filter会插入在所有globalFilter之后。