Gateway配置介绍
路由断言工厂(Route Predicate Factories)配置
SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体如下:
1.基于Datetime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
1》AfterRoutePredicateFactory:接收一个日期参数,判断请求日期是否晚于指定日期
2》BeforeRoutePredicateFactory:接收一个日期参数,判断请求日期是否早于指定日期
3》BetweenRoutePredicateFactory:接收两个日期参数,判断请求日期是否在指定时间段内
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
2.基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中
- RemoteAddr=192.168.1.1/24
3.基于Cookie的断言工厂
CookieRoutePredicateFactory:接收两个参数,cookie名字和一个正则表达式。判断请求cookie是否具有给定名称且值与正则表达式匹配。
- Cookie=chocolate, ch.p
4.基于Header的断言工厂
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。判断请求Header是否具有给定名称且正则表达式匹配。
- Header=X-Request-Id, \d+
5.基于Host的断言工厂
HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。
- Host=**.somehost.org,**.anotherhost.org
6.基于Method请求方法的断言工厂
MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。
- Method=GET,POST
7.基于Path请求路径的断言工厂
PathRoutePredicateFactory:接收一个参数,判断请求的URL部分是否满足路径规则。
- Path=/red/{segment},/blue/{segment}
8.基于Query请求参数的断言工厂
QueryRoutePredicateFactory:接收两个参数,请求param和正则表达式,判断请求参数是否具有给定名称且值与正则表达式匹配。
- Query=green
- Query=red, gree.
9.基于路由权重的断言工厂
WeightRoutePredicateFactory:接收一个[组名,权重],然后对于同一组内的路由按照权重转发。
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
自定义路由断言工厂
自定义路由断言工厂需要继承AbstractRoutePredicateFactory类,重写apply方法的逻辑。在apply方法中可以通过exchange.getRequest()拿到ServerHttpRequest对象,从而可以获取到请求的参数、请求方式、请求头等信息。
注意:命名需要以RoutePredicateFactory结尾
1》必须是spring组件bean
2》类上必须加上RoutePredicateFactory作为结尾
3》必须继承AbstractRoutePredicateFactory
4》必须声明静态内部类 声明属性来接收 配置文件中对应的断言的信息
5》需要结合shortcutFieldOrder进行绑定
6》通过apply进行逻辑判断 true就是匹配成功 false匹配失败
1.自定义路由断言工厂
@Slf4j
@Component
public class CheckRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckRoutePredicateFactory.Config> {
public CheckRoutePredicateFactory() {
super(CheckRoutePredicateFactory.Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList("name");
}
public Predicate<ServerWebExchange> apply(CheckRoutePredicateFactory.Config config) {
return new GatewayPredicate() {
public boolean test(ServerWebExchange exchange) {
if(config.getName().equals("mu")){
return true;
}
return false;
}
};
}
/**
* 用于接收配置文件中 断言的信息
*/
@Validated
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
2.application.yml配置
server:
port: 8088
# 应用名称(nacos会将该名称当做服务名称)
spring:
application:
name: api-gateway
cloud:
# gateway的配置
gateway:
# 路由规则
routes:
- id: order_route # 路由的唯一标识,路由到order
uri: lb://order-service # 需要转发的地址 lb: 使用nacos中的本地负载均衡策略
# 断言规则 用于路由规则的匹配
predicates:
- Path=/order/**
- Check=mu
# 配置nacos
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
3.测试
Giteway过滤工厂(GatewayFilter Factories)配置
Gateway内置了很多的过滤器工厂,我们通过一些过滤器工厂可以进行一些业务逻辑处理器,比如添加剔除响应头,添加去除参数等。
过滤器工厂 | 作用 | 参数 |
---|---|---|
AddRequestHeader | 为原始请求添加Header | Header的名称及值 |
AddRequestParameter | 为原始请求添加请求参数 | 参数名称及值 |
DedupeResponseHeader | 剔除响应头中重复的值 | 需要去重的Header名称及去重策略 |
Hystrix | 为路由引入Hystrix的断路器保护 | HystrixCommand的名称 |
FallbackHeaders | 为fallbackUn的请求头中添加具体的异常信息 | Header的名称 |
PrefixPath | 为原始请求路径添加前缀 | 前端路径 |
PreserveHostHeader | 为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host | 无 |
RequestRateLimiter | 用于对请求限流,限流算法为令牌桶 | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
RedirectTo | 将原始请求重定向到指定的URL | http状态码及重定向的url |
RemoveHopByHopHeadersFilter | 为原始请求删除IETF组织规定的一系列Header | 默认就会启用,可以通过配置指定仅删除哪些Header |
RemoveRequestHeader | 为原始请求删除某个Header | Header名称 |
RemoveResponseHeader | 为原始响应删除某个Header | Header名称 |
RewritePath | 重写原始的请求路径 | 原始路径正则表达式以及重写后路径的正则表达式 |
RewriteResponseHeader | 重写原始响应中的某个Header | Header名称、值的正则表达式,重写后的值 |
SaveSession | 在转发请求之前,强制执行WebSession:save操作 | 无 |
secureHeaders | 为原始响应添加一系列起安全作用的响应头 | 无,支持修改这些安全响应头的值 |
SetPath | 修改原始的请求路径 | 修改后的路径 |
SetResponseHeader | 修改原始响应中某个Header的值 | Header名称,修改后的值 |
SetStatus | 修改原始响应的状态码 | HTTP状态码,可以是数字,也可以是字符串 |
StripPrefix | 用于截断原始请求的路径 | 使用数字表示要截断的路径的数量 |
Retry | 针对不同的响应进行重试 | retries、statuses、methods、series |
RequestSize | 设置允许接收最大请求包的大小,如果请求包大小超过设置的值,则返回413Payload Too Large | 要求包大小,单位为字节,默认值为5M |
ModifyRequestBody | 在转发请求之前修改原始请求体内容 | 修改后的请求体内容 |
ModifyResponseBody | 修改原始响应体的内容 | 修改后的响应体内容 |
1.添加请求头
server:
port: 8088
# 应用名称(nacos会将该名称当做服务名称)
spring:
application:
name: api-gateway
cloud:
# gateway的配置
gateway:
# 路由规则
routes:
- id: order_route # 路由的唯一标识,路由到order
uri: lb://order-service # 需要转发的地址 lb: 使用nacos中的本地负载均衡策略
# 断言规则 用于路由规则的匹配
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-color, red # 添加请求头
# 配置nacos
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
测试
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/header")
public String header(@RequestHeader("X-Request-color") String color){
String result = restTemplate.getForObject("http://stock-service/stock/reduct", String.class);
log.info("下单成功!");
return "Hello World !" + result + color;
}
}
2.为匹配的路由统一添加前缀
server:
port: 8088
# 应用名称(nacos会将该名称当做服务名称)
spring:
application:
name: api-gateway
cloud:
# gateway的配置
gateway:
# 路由规则
routes:
- id: order_route # 路由的唯一标识,路由到order
uri: lb://order-service # 需要转发的地址 lb: 使用nacos中的本地负载均衡策略
# 断言规则 用于路由规则的匹配
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-color, red # 添加请求头
- PrefixPath=/mu # 添加前缀 对应微服务需要配置context-path
# 配置nacos
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
order-nacos中需要配置
server:
port: 8020
servlet:
context-path: /mu
测试:
3.重定向操作
server:
port: 8088
# 应用名称(nacos会将该名称当做服务名称)
spring:
application:
name: api-gateway
cloud:
# gateway的配置
gateway:
# 路由规则
routes:
- id: order_route # 路由的唯一标识,路由到order
uri: lb://order-service # 需要转发的地址 lb: 使用nacos中的本地负载均衡策略
# 断言规则 用于路由规则的匹配
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-color, red # 添加请求头
- PrefixPath=/mu # 添加前缀 对应微服务需要配置context-path
- RedirectTo=302, https://www.baidu.com/ #添加重定向
# 配置nacos
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
测试:
4.自定义过滤器工厂
继承AbstractNameValueGatewayFilterFactory且我们的自定义名称必须要以GatewayFilterFactory结尾并交给spring管理。
@Component
public class CheckAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> {
public CheckAuthGatewayFilterFactory() {
super(CheckAuthGatewayFilterFactory.Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList("value");
}
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(StringUtils.isNotBlank(name)){
if(config.getValue().equals(name)){
return chain.filter(exchange);
}else{
//返回404 结束
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
}
//正常请求
return chain.filter(exchange);
}
};
}
public static class Config {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
配置自定义的过滤器工厂
server:
port: 8088
# 应用名称(nacos会将该名称当做服务名称)
spring:
application:
name: api-gateway
cloud:
# gateway的配置
gateway:
# 路由规则
routes:
- id: order_route # 路由的唯一标识,路由到order
uri: lb://order-service # 需要转发的地址 lb: 使用nacos中的本地负载均衡策略
# 断言规则 用于路由规则的匹配
predicates:
- Path=/order/**
filters:
- CheckAuth=mry
- PrefixPath=/mu # 添加前缀 对应微服务需要配置context-path
# 配置nacos
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
测试:
Gateway全局过滤器
局部过滤器和全局过滤器区别:
局部:局部针对某个路由,需要在路由中进行配置
全局:针对所有路由请求,一旦定义就会投入使用
GlobalFilter接口和GatewayFilter有一样的接口定义,只不过,GlobalFilter会作用于所有路由。
1.LoadBalancerClientFilter
LoadBalancerClientFilter会查看exchange的属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的值(一个URL),如果该值的scheme是lb,比如:lb://myservice,它将会使用Spring Cloud的LoadBalancerClient来将myservice解析成实际的host和port,并替换掉ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的内容。
其实就是用来整合负载均衡的Ribbon的
@Slf4j
@Component
public class LogFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info(exchange.getRequest().getPath().value());
return chain.filter(exchange);
}
}
测试:
Reactor Netty访问日志
要启动Reactor Netty 访问日志,请设置-Dreactor.netty.http.server.accessLogEnabled=true
它必须是Java系统属性,而不是Spring Boot属性。
您可以将日志记录系统配置为具有单独的访问日志文件。以下示例创建一个Logback配置:
Gateway跨域配置(CORS Configuration)
通过yml配置的方式
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': # 允许跨域访问的资源
allowedOrigins: "https://docs.spring.io" # 跨域允许来源
allowedMethods:
- GET
- POST
通过java配置的方式
@Configuration
public class CorsConfig{
@Bean
public CorsWebFilter corsFilter(){
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}