万世威 2020-10-16
基于 Spring 5, Spring Boot 2 and Project Reactor
动态路由
Predicates 和 filters 作用于特定路由
集成了 Hystrix 断路器
集成了 Spring Cloud DiscoveryClient
易于编写的 Predicates 和 Filters
限流
路径重写
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
spring:
application:
name: nacos-gateway-server
cloud:
gateway:
routes:
- id: provider
uri: http://127.0.0.1:9002/
predicates:
- Path=/dist/** # url 中匹配这个地址后,转发到 uri 上,uri+Path 组成
问题:基本配置里面硬编码 uri 地址,不能做到负载、服务自动发现
解决:配置之前的 Nacos 动态服务功能实现
<!-- 引入依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
/* main 方法上开启服务发现功能 */
@EnableDiscoveryClient
public class GatewayMain {}
spring:
application:
name: nacos-gateway-server
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: provider
# uri: http://127.0.0.1:9002/
uri: lb://quick-provider #配置提供者的注册的服务名spring.application.name
predicates:
- Path=/dist/**
# after
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
# cookie
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
# method
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
更多可参考官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html#gateway-request-predicates-factories
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
public AgeRoutePredicateFactory(){
super(AgeRoutePredicateFactory.Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("minAge", "maxAge");
}
@Override
public Predicate<ServerWebExchange> apply(AgeRoutePredicateFactory.Config config) {
return serverWebExchange -> {
String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("age");
if (!StringUtils.isEmpty(ageStr)) {
int age = Integer.parseInt(ageStr);
return age >= config.getMinAge() && age <= config.getMaxAge();
}
return false;
};
}
public static class Config {
private int minAge;
private int maxAge;
public Config() { }
// 省略 getter、setter
}
}
predicates:
- Age=18,30
1、Config 类 必须要有 构造函数
2、配置中 Age 和类名保持一致,且类名格式固定,以 RoutePredicateFactory 结尾
3、18-30,按照 shortcutFieldOrder 方法参数顺序注入值
4、具体可参考内置的 Predicate Factory,采用 xxxRoutePredicateFactory
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories
/* 使用此方式可在 yaml 中配置 */
@Component
public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestTimeGatewayFilterFactory.Config> {
private static final Log log = LogFactory.getLog(GatewayFilter.class);
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
private static final String KEY = "withParams";
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(KEY);
}
public RequestTimeGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
if (startTime != null) {
StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
.append(": ")
.append(System.currentTimeMillis() - startTime)
.append("ms");
if (config.isWithParams()) {
sb.append(" params:").append(exchange.getRequest().getQueryParams());
}
log.info(sb.toString());
}
})
);
};
}
public static class Config {
private boolean withParams;
public boolean isWithParams() {
return withParams;
}
public void setWithParams(boolean withParams) {
this.withParams = withParams;
}
}
}
gateway:
routes:
- id: provider
uri: lb://quick-provider
filters:
- RequestTime=true
predicates:
- Path=/dist/**
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html#_global_filters
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("invoke auth filter..");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;// 返回值越小,优先级越高
}
}
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html
https://github.com/spring-cloud/spring-cloud-gateway