Gateway - 网关
功能
原理
依赖引入
也可以引入 loadbalancer 让网关负载均衡地分发请求
xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
基础配置
在 application.yml 配置全局跨域 以及请求路径前缀 /api/order/** ===> 转为 /**
yaml
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowed-origin-patterns: '*'
allowed-headers: '*'
allowed-methods: '*'
routes:
- id: order-route
uri: lb://service-order
predicates:
- Path=/api/order/**
filters:
- RewritePath=/api/order/(?<segment>.*), /$\{segment}
- id: product-route
uri: lb://service-product
predicates:
- Path=/api/product/**
filters:
- RewritePath=/api/product/(?<segment>.*), /$\{segment}
路由配置源码
网关路由配置项即
RouteDefinition
类的属性
断言 Predicate
Gateway 定义了一系列默认的断言工厂
自定义断言工厂
实现一个自定义断言工厂
java
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {
public VipRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
//localhost/search?q=haha&user=leifengyang
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
ServerHttpRequest request = serverWebExchange.getRequest();
String first = request.getQueryParams().getFirst(config.param);
if (StringUtils.hasText(first) && first.equals(config.value)) {
return true;
}
return false;
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("param", "value");
}
@Data
@Validated
public static class Config {
@NotEmpty
private String param;
@NotEmpty
private String value;
}
}
断言包括 Path Query 还有自定义的 Vip 断言工厂
yaml
routes:
- id: bing-route
uri: https://cn.bing.com/
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
- name: Vip
args:
param: user
value: leifengyang
order: 3
路径为 /search 参数为 q=haha Vip参数 user=leifengyang 就成功被断言
过滤器
默认过滤器
将请求 /api/order/** 重写为 /**
yaml
- id: order-route
uri: lb://service-order
predicates:
- Path=/api/order/**
filters:
- RewritePath=/api/order/(?<segment>.*), /$\{segment}
全局过滤器
案例:定义全局过滤器记录所有请求处理花费时间
java
/**
* 全局过滤器,记录请求时间与响应时间差
*/
@Component
@Slf4j
public class RtGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String uri = request.getURI().toString();
long start = System.currentTimeMillis();
log.info("请求【{}】开始:时间:{}",uri,start);
//================ 以上前置逻辑 ===========
Mono<Void> filter = chain.filter(exchange) // 放行 10s
.doFinally((result) -> {
// 响应式编程 后置逻辑
long end = System.currentTimeMillis();
log.info("请求【{}】结束:时间:{},耗时:{}ms",uri,end,end-start);
});
return filter;
}
@Override
public int getOrder() {
return 0;
}
}
自定义过滤器
自定义过滤器,每次响应之前添加一个一次性令牌,支持 uuid ,jwt 格式,可以在 yml 文件中配置
java
@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//每次响应之前添加一个一次性令牌,支持 uuid ,jwt 等格式
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
String value = config.getValue();
if ("uuid".equalsIgnoreCase(value)) {
value = UUID.randomUUID().toString();
}
if ("jwt".equalsIgnoreCase(value)) {
value = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE2MjQyNjIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
}
headers.add(config.getName(),value);
}));
}
};
}
}
在
application.yml
中配置自定义的过滤器 OnceToken 作为默认过滤器
yaml
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- Path=/api/order/**
filters:
- RewritePath=/api/order/(?<segment>.*), /$\{segment}
order: 0
default-filters:
- AddResponseHeader=X-Powered-By, Spring Cloud Gateway
- OnceToken=X-Response-Token, jwt