Route Predicate Factories
After Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
这个路由匹配“美国丹佛时间2017-01-20 17:42”之后的任意请求
Header Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
这个路由匹配“请求头包含X-Request-Id并且其值匹配正则表达式\d+”的任意请求
Method Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET
这个路由匹配任意GET请求
Path Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Path=/foo/{segment},/bar/{segment}
这个路由匹配这样路径的请求,比如:/foo/1 或 /foo/bar 或 /bar/baz
Query Route Predicate Factory
这个Predicate有两个参数:一个必须的参数名和一个可选的正则表达式
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=baz
这个路由匹配“查询参数中包含baz”的请求
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=foo, ba.
这个路由匹配“查询参数中包含foo,并且其参数值满足正则表达式ba.”的请求,比如:bar,baz
RemoteAddr Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
这里路由匹配远程地址是这样的请求,例如:192.168.1.10
GatewayFilter Factories(网关过滤器)
路由过滤器允许以某种方式修改传入的HTTP请求或传出HTTP响应。路由过滤器的作用域是特定的路由。Spring Cloud Gateway包含许多内置的网关过滤器工厂。
AddRequestHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
对于所有匹配的请求,将会给传给下游的请求添加一个请求头 X-Request-Foo:Bar
AddRequestParameter GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=foo, bar
对于所有匹配的请求,将给传给下游的请求添加一个查询参数 foo=bar
AddResponseHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar
Hystrix GatewayFilter Factory
Hystrix网关过滤器允许你将断路器引入网关路由,保护你的服务免受级联失败的影响,并在下游发生故障时提供预备响应。
为了启用Hystrix网关过滤器,你需要引入 spring-cloud-starter-netflix-hystrix
Hystrix网关过滤器需要一个name参数,这个name是HystrixCommand的名字
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: https://example.org
filters:
- Hystrix=myCommandName
给这个过滤器包装一个名字叫myCommandName的HystrixCommand
Hystrix网关过滤器也接受一个可选的参数fallbackUri,但是目前只支持forward:前缀的URL。也就是说,如果这个fallback被调用,请求将被重定向到匹配的这个URL。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingserviceendpoint
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis
- RewritePath=/consumingserviceendpoint, /backingserviceendpoint
当fallback被调用的时候,请求将被重定向到/incaseoffailureusethis
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: Hystrix
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
在这个例子中,专门定义了一个端点来处理/fallback请求,它在localhost:9994上。也就是说,当fallback被调用的时候将重定向到http://localhost:9994/fallback
PrefixPath GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
所有匹配的请求都将加上前缀/mypath。例如,如果请求是/hello,那么经过这个过滤器后,发出去的请求变成/mypath/hello
RequestRateLimiter GatewayFilter Factory
RequestRateLimiter网关过滤器使用一个RateLimiter实现来决定是否当前请求可以继续往下走。如果不能,默认将返回HTTP 429 - Too Many Requests
这个过滤器接受一个可选的参数keyResolver,这个参数是一个特定的rate limiter
keyResolver是实现了KeyResolver接口的一个Bean。
在配置的时候,使用SpEL按名称引用Bean。#{@myKeyResolver}是一个SpEL表达式,表示引用名字叫myKeyResolver的Bean。
KeyResolver.java
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver默认的实现是PrincipalNameKeyResolver,它从ServerWebExchange中检索Principal,并调用Principal.getName()方法。
默认情况下,如果KeyResolver没有找到一个key,那么请求将会被denied(译:否认,拒绝)。这种行为可以通过spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true or false) 和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code 属性来进行调整.
Redis RateLimiter
需要引用 spring-boot-starter-data-redis-reactive
这个逻辑使用令牌桶算法
redis-rate-limiter.replenishRate : 允许用户每秒处理多少个请求。这是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity : 用户在一秒钟内允许执行的最大请求数。这是令牌桶可以容纳的令牌数量。将此值设置为0将阻塞所有请求。
一个稳定的速率是通过将replenishRate 和 burstCapacity设为相同的值来实现的。也可以将burstCapacity设得比replenishRate大,以应对临时爆发的流量。在这种情况下,需要允许速率限制器在突发事件之间间隔一段时间,因为连续两次突发事件将导致丢弃请求(HTTP 429 - Too Many Requests)
application.yml
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
这里定义了每个用户的请求速率限制为10。允许使用20个请求,但是在接下来的一秒中,只有10个请求可用。
spring cloud gateway 二次开发之动态路由注意事项
网关开发的过程中,因为有对某些服务进行动态的上下线的需求,所以进行了动态路由的开发
数据库里的断言器信息不能为空,如果在添加路由信息的时候没有传断言器,比如这样
{
"id":"test",
"predicates":[],
"filters":[],
"uri":"lb://test",
"order":0
}
会抛出异常
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.combinePredicates(RouteDefinitionRouteLocator.java:221)
at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.convertToRoute(RouteDefinitionRouteLocator.java:143)
我们看路由信息类的时候,可以发现断言器是一个List,RouteDefinitionRouteLocator下边有这个方法,会先取List中第一个断言器,然后与之后的断言器做组合
private AsyncPredicate<ServerWebExchange> combinePredicates(
RouteDefinition routeDefinition) {
List<PredicateDefinition> predicates = routeDefinition.getPredicates();
//取出第一个断言器
AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0));
//取出后续断言器
for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
//第一个断言器和后续断言器做 and 操作
predicate = predicate.and(found);
}
return predicate;
}
如果没有填断言器信息,就会报数组越界异常
断言器的名字不能随便取
{
"id":"test",
"predicates":[
{
"name":"zuibuxing",
"args":{
"_genkey_0":"/test/**"
}
}
],
"filters":[
],
"uri":"lb://test",
"order":0
}
网友评论