SpringCloud gateway内置过滤器之二

1、FallbackHeaders GatewayFilter

FallbackHeaders允许在触发熔断转发到外部应用程序中的fallbackUri的请求的标头中添加Spring Cloud CircuitBreaker执行异常详细信息。例如:

spring:
cloud:
gateway:
enabled: true
routes:
- id: Goods-Server # 路由 id,唯一标识
uri: lb://producer
predicates:
# - Path=/** # 断言,路由匹配条件,匹配 /product 开头的所有 api
- Path=/producer/{segment}
filters:
- StripPrefix=1
- AddRequestHeader=X-Request-red, Blue-{segment}
- AddRequestParameter=red, bar-{segment}
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/myfallback
statusCodes:
- 500
- "NOT_FOUND"
- id: ingredients-fallback
uri: http://localhost:8002/
predicates:
- Path=/myfallback
filters:
- name: FallbackHeaders
args:
rootCauseExceptionMessageHeaderName: Test-Header

8002是Producer服务的端口。触发熔断时会将请求转发到Producer的/myfallback。先注释gatewayServer里面的Fallback Controller,确保降级回调到Producer的/myfallback.

 

修改Producer服务:

@RequestMapping("/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
System.out.println(request.getHeader("x-request-red"));
System.out.println(request.getParameter("red"));
int i = 10 / 0;
return "hello," + name + "," + port;
}

确保调用服务引发异常。

 
在Producer模块增加服务降级回调:

@RestController
public class FallbackController {
private String dateStr(){
return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
}

/**
* 返回字符串类型
* @return
*/
@GetMapping("/myfallback")
public String helloStr(HttpServletRequest request) {
String s= request.getHeader("Test-Header");
System.out.println("producer:"+s);
return "producer myfallback, " + dateStr();
}
}

访问 http://localhost:8500/producer/hello ,查看Producer控制台,发现:
 

 

如果将FallbackController移到gatewayServer模块,则服务降级回调/myfallback获取不到请求头。

 
还可以通过设置以下参数的值(以默认值显示)来覆盖配置中标头的名称:

  • executionExceptionTypeHeaderName ("Execution-Exception-Type")

  • executionExceptionMessageHeaderName ("Execution-Exception-Message")

  • rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")

  • rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")

2、MapRequestHeader GatewayFilter

MapRequestHeader GatewayFilter采用fromHeader和toHeader参数。它创建一个新的命名标头(toHeader),并从传入的http请求中的现有命名标头(fromHeader)中提取值。如果输入标头不存在,则过滤器没有影响。如果新的命名标头已经存在,则其值将使用新值进行扩充。例如:

spring:
cloud:
gateway:
enabled: true
routes:
- id: Goods-Server # 路由 id,唯一标识
uri: lb://producer
predicates:
# - Path=/** # 断言,路由匹配条件,匹配 /product 开头的所有 api
- Path=/producer/{segment}
filters:
- StripPrefix=1
- MapRequestHeader=X-Request-Red, Blue

 

Producer服务的Controller:

@RequestMapping("/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
System.out.println(request.getHeader("X-Request-Red"));
System.out.println(request.getHeader("blue"));
return "hello," + name + "," + port;
}

 

用Postman调用http://localhost:8500/producer/hello:
 

 

查看Producer控制台:
 

 

3、PrefixPath GatewayFilter

PrefixPath GatewayFilter将在匹配的请求前面加上前缀。例如:

spring:
cloud:
gateway:
enabled: true
routes:
- id: Goods-Server # 路由 id,唯一标识
uri: lb://producer
predicates:
# - Path=/** # 断言,路由匹配条件,匹配 /product 开头的所有 api
- Path=/producer/{segment}
filters:
- StripPrefix=1
- PrefixPath=/mypath

比如请求路径是/producer/hello,StripPrefix会移除/producer,PrefixPath会加前缀,所以请求路径是/mypath/hello。访问http://localhost:8500/producer/hello报404。Producer服务的请求路径从:

@RequestMapping("/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
return "hello," + name + "," + port;
}

修改为:

@RequestMapping("/mypath/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
return "hello," + name + "," + port;
}

访问 http://localhost:8500/producer/hello ,成功。

4、PreserveHostHeader GatewayFilter

PreserveHostHeader GatewayFilter没有参数。此筛选器设置一个请求属性,路由过滤器检查该属性以确定是否应发送原始主机标头,而不是HTTP客户端确定的主机标头。

spring:
cloud:
gateway:
enabled: true
routes:
- id: Goods-Server # 路由 id,唯一标识
uri: lb://producer
predicates:
# - Path=/** # 断言,路由匹配条件,匹配 /product 开头的所有 api
- Path=/producer/{segment}
filters:
- StripPrefix=1
- PreserveHostHeader

5、RequestRateLimiter GatewayFilter

RequestRateLimiter GatewayFilter是限速过滤器。如果被限速会返回HTTP 429 - Too Many Requests。使用Redis来限流。所使用的算法是令牌桶算法。

spring:
cloud:
gateway:
enabled: true
routes:
- id: Goods-Server # 路由 id,唯一标识
uri: lb://producer
predicates:
# - Path=/** # 断言,路由匹配条件,匹配 /product 开头的所有 api
- Path=/producer/{segment}
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 20
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
key-resolver: "#{@keyResolver}"
redis:
host: localhost
port: 6379

replenishRate是希望用户在不丢弃任何请求的情况下每秒可以执行的请求数。这是填充令牌桶的速率。
burstCapacity是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以容纳的令牌数量。将此值设置为零将阻止所有请求。
requestedTokens是一个请求花费的令牌数。这是针对每个请求从存储桶中获取的令牌数量,默认为1。
KeyResolver接口允许可插入策略用于限制请求的密钥。#{@keyResolver}里面的keyResolver是Bean的名字。

 

在GatewayServer添加依赖并配置:


org.springframework.boot
spring-boot-starter-data-redis-reactive
3.0.6

@Configuration
public class MyConfig {

@Bean("keyResolver")
public KeyResolver pathKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
}
}

 

使用jmeter来测试限流:
添加线程组:
 

 
设置线程数,循环次数:
 

 

添加http请求:
 

 

配置ip,端口,url等:
 

 

添加汇总报告:
 

 

点击执行后查看汇总报告:
 

 

posted @ 2023-05-06 11:19  shigp1  阅读(158)  评论(0)    收藏  举报