二十五、Gateway全局过滤器

全局过滤器GlobalFilte 接口与 GatewayFilter 具有相同的签名,这些特定的过滤器有条件的应用到所有的路由上。

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.0.RC1/reference/html/#global-filters

组合使用GlobalFilter和GatewayFilter

当请求进来的时候,过滤器Web处理器将会将所有的GlobalFilter 实例和所有特定的GatewayFilter 路由实例添加到过滤器filter链中,该组合的过滤器按org.springframework.core.Ordered接口排序,通过实现getOrder()方法来设置。

由于Spring Cloud Gateway 区分了过滤器逻辑执行器的”前”阶段和”后”阶段,因此优先级最高的过滤器在pre 阶段中处于第一个,而在post 阶段处于最后一个。

CustomGlobalFilter.java

1
2
3
4
5
6
7
8
9
10
11
12
public class CustomGlobalFilter implements GlobalFilter,Ordered {

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange);
}

@Override
public int getOrder() {
return 0;
}
}

注意:数值越小,越靠前执行。

LoadBalancerClient

LoadBalancerClientFilter在交换属性查找一个URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果url有一个lb方案(即lb://myservice),它将使用Spring Cloud LoadBalancerClient将名称(myservice在前面的示例中)解析为实际的主机和端口,并在同一属性中替换URI。未经修改的原始url将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表。过滤器还将在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性中查找是否相等lb,然后应用相同的规则

application.yaml

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**

上面的介绍难以理解,其实通过代码可以看出,就是使用lb 来指定是否使用ribbon负载均衡。可以发现,这里Gateway也是使用ribbon来实现负载均衡的。

默认情况下,当一个服务示例不能被LoadBalancer发现,将会返回503, 我们可以配置spring.cloud.gateway.loadbalancer.use404 = false 来使得Gateway返回404.

我们建议使用ReactiveLoadBalancerClientFilter。您可以通过设置spring.cloud.loadbalancer.ribbon.enabled的值为false来使用ReactiveLoadBalancerClientFilter.

ReactiveLoadBalancerClientFilter

如上,见识使用这个,只需要将spring.cloud.loadbalancer.ribbon.enabled设置为false就可以了。

Sentinel 整合Gateway

1
2
3
4
5
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
* @author hao.ouYang
* @create 2019-10-29 14:15
*/
@Configuration
public class GatewayConfiguration {

private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;

public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}

// 这两个在SentinelSCGAutoConfiguration已经配置好了
/*@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}

@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}*/

/*@PostConstruct
public void doInit() {
initCustomizedApis();
initGatewayRules();
}*/

/*可以使用管理控制台进行管理*/
/*初始化自定义的Api*/
private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();

// some_customized_api api名称
ApiDefinition api1 = new ApiDefinition("some_customized_api")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/ahas"));
add(new ApiPathPredicateItem().setPattern("/product/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});

ApiDefinition api2 = new ApiDefinition("another_customized_api")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api1);
definitions.add(api2);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}


/*初始化网关流控规则*/
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("aliyun_route")
.setCount(10)
.setIntervalSec(1)
);

rules.add(new GatewayFlowRule("aliyun_route")
.setCount(2)
.setIntervalSec(2)
.setBurst(2)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP)
)
);
rules.add(new GatewayFlowRule("httpbin_route")
.setCount(10)
.setIntervalSec(1)
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)
.setMaxQueueingTimeoutMs(600)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER)
.setFieldName("X-Sentinel-Flag")
)
);
rules.add(new GatewayFlowRule("httpbin_route")
.setCount(1)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("pa")
)
);
rules.add(new GatewayFlowRule("httpbin_route")
.setCount(2)
.setIntervalSec(30)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("type")
.setPattern("warn")
.setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_CONTAINS)
)
);

rules.add(new GatewayFlowRule("some_customized_api")
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(5)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("pn")
)
);
GatewayRuleManager.loadRules(rules);
}
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×