网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们本次采用前面学过的 sentinel 组件来实现网关的限流。
从1.6.0版本开始,sentinel提供了springcloud gateway的适配模块,可以提供两种资源维度的限流:
- route维度:即在spring配置文件中配置的路由条目,资源名为对应的routeld;
- 自定义api维度:用户可以利用sentinel提供的api来自定义一些api分组;
route限流
导入依赖
<dependency>
<groupid>com.alibaba.csp</groupid>
<artifactid>sentinel-spring-cloud-gateway-adapter</artifactid>
</dependency>
编写配置类
基于sentinel的gateway限流是通过其提供的filter来完成的,使用时只需注入对应的sentinelgatewayfilter
实例以及sentinelgatewayblockexceptionhandler
实例即可。
@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;
}
//初始化一个限流的过滤器
@bean
@order(ordered.highest_precedence)
public globalfilter sentinelgatewayfilter() {
return new sentinelgatewayfilter();
}
//配置初始化的限流参数
@postconstruct
public void initgatewayrules() {
set<gatewayflowrule> rules = new hashset<>();
rules.add(new gatewayflowrule("shop-product")//资源名称,对应路由id
.setcount(1)//限流阀值
.setintervalsec(1)//统计时间窗口,单位是秒,默认是1秒
);
gatewayrulemanager.loadrules(rules);
}
//配置限流异常处理器
@bean
@order(ordered.highest_precedence)
public sentinelgatewayblockexceptionhandler sentinelgatewayblockexceptionhandler() {
return new sentinelgatewayblockexceptionhandler(viewresolvers, servercodecconfigurer);
}
//自定义限流异常页面
@postconstruct
public void initblockhandlers() {
blockrequesthandler blockrequesthandler = new blockrequesthandler() {
@override
public mono<serverresponse> handlerequest(serverwebexchange serverwebexchange, throwable throwable) {
map map= new hashmap<>();
map.put("code", 0);
map.put("message", "接口被限流了");
return serverresponse
.status(httpstatus.ok)
.contenttype(mediatype.application_json_utf8)
.body(bodyinserters.fromobject(map));
}
} ;
gatewaycallbackmanager.setblockhandler(blockrequesthandler);
}
}
其中,gatewayflowrule 网关限流规则中提供了如下属性:
- resource:资源名称,可以是网关中的route名称或者用户自定义的api分组名称。
- resourcemode:资源模型,限流规则是针对api gateway的 route
(resource_mode_route_id)
还是用户在sentinel 中定义的api分组(resource_mode_custom_api_name)
,默认route。 - grade:限流指标维度,同限流规则的 grade 字段。
- count:限流阈值。
- intervalsec:统计时间窗口,单位是秒, 默认是1 秒。
- controlbehavior:流量整形的控制效果,同限流规则的controlbehavior字段,目前支持快速失败和匀速排队两种模式,默认快速失败。
- burst:应对突发请求时额外允许的请求数目。
- maxqueueingtimeoutms:匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。
- paramitem:参数限流配置。若不提供,则代表针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换热点规则。其中的字段如下:
-
- arsestrategy: 从请求中提取参数的策略,目前支持提取来源ip(param_parse_strategy_client_ip)、host(param_parse_strategy_host)、任意header(param_parse_strategy_header)和任意url 参数(param_parse_strategy_url_param)四种模式。
-
- fieldname:若提取策略选择header模式或者url参数模式,则需要指定对应的header名称或url参数名称。
-
- pattern和matchstrategy: 为后续参数匹配特性预留,目前末实现。
测试
在一秒钟内多次访问http://localhost:7000/product/product/1?token=1232
就可以看到限流启作用了。
自定义api分组
自定义api分组是一种更细粒度的限流规则定义
//配置初始化的限流参数
@postconstruct
public void initgatewayrules() {
set<gatewayflowrule> rules = new hashset<>();
rules.add(new gatewayflowrule("shop_product_api").setcount(1).setintervalsec(1));
rules.add(new gatewayflowrule("shop_order_api").setcount(1).setintervalsec(1));
gatewayrulemanager.loadrules(rules);
}
//自定义api分组
@postconstruct
private void initcustomizedapis(){
set<apidefinition> definitions = new hashset<>();
//定义小组1
apidefinition api1 = new apidefinition("shop_product_api")
.setpredicateitems(new hashset<apipredicateitem>(){{
//以/product/product/api1开头的请求
add(new apipathpredicateitem().setpattern("/product/product/**")
.setmatchstrategy(sentinelgatewayconstants.url_match_strategy_prefix));
}});
//定义小组2
apidefinition api2 = new apidefinition("shop_order_api")
.setpredicateitems(new hashset<apipredicateitem>(){{
//完全匹配/order/order2/message
add(new apipathpredicateitem().setpattern("/order/order2/message"));
}});
definitions.add(api1);
definitions.add(api2);
gatewayapidefinitionmanager.loadapidefinitions(definitions);
}
在一秒钟内多次访问http://localhost:7000/product/product/1?token=1232
也可以看到限流启作用了。
总结
到这儿,gateway 服务网关限流的内容就已经介绍完了。下一篇将为大家带来链路追踪sleuth相关的文章,敬请期待吧!
后续的文章,我们将继续完善我们的微服务系统,集成更多的alibaba组件。想要了解更多java后端知识,请点击文末名片与我交流吧。留下您的一键三连,让我们在这个寒冷的东西互相温暖吧!
发表评论