假设我们要调用阿里的某个API,但是该API每秒QPS限制为50次,假设集群中存在多台机器同时调用该API的情况,如何控制整个集群中该API调用次数在50以内,避免接口报错
假设开发的系统需要提供http接口给第三方调用,为了防止第三方恶意调用接口爬取数据,我们需要限制http接口请求QPS为50
两个场景都是基于接口资源层面的限流,本文介绍Sentinel结合Ahas云上控制台实现的集群流控功能
com.alibaba.csp
ahas-sentinel-client
1.2.1
注意:ahas-sentinel-client 1.2.x 仅兼容 Sentinel 1.5.0 及以上版本;ahas-sentinel-client 1.1.x 仅兼容 Sentinel 1.4.1 和 1.4.2 版本。
ahas-sentinel-client 中会包含 sentinel-core 以及集群限流等必要依赖(基于 Sentinel 1.5.1 版本),以及连接 AHAS Sentinel 控制台所需模块(鉴权、通信、动态数据源等),下面基于ahas-sentinel-client 1.1.2版本做介绍
操作步骤如下
注意若应用运行在非阿里云 ECS 环境或本地,需要在左上角选择切换公网环境
点击应用接入后拿到启动参数
启动参数如下,需要加到项目启动参数中
-Dproject.name=AppName -Dahas.license=
其中 project.name 代表应用名(会显示在控制台),ahas.license 代表自己的授权 license,为上图中红色划线部分,自己开通AHAS后获取,本地调试时再加入如下启动参数
-Dcsp.sentinel.log.use.pid=true
上述介绍的是通过JVM启动参数的接入方式,也有通过配置文件的方式,具体可以看官方接入文档介绍
https://help.aliyun.com/document_detail/110599.html?spm=a2c4g.11186623.6.584.73bc5365yz8C36
要实现集群限流,必须配置一个Token Server,获取到令牌的机器才有权限调用接口,这一步大家先看流程,可以先不配置。
AHAS中集成了嵌入式的Token Server(即Web服务机器可以被指定为Token Server),方便使用,也有独立部署模式的Token Server,需要自己单独部署,Token Server部署方案直接摘自官方示例中的说明
https://github.com/alibaba/Sentinel/wiki/AHAS-Sentinel-集群限流控制台示例
先进入自己服务对应的Token Server列表,链接如下
https://ahas.console.aliyun.com/#/SystemGuardClusterServerPage?appName=web-demo®ionId=public&_k=f9zjb1
点击新增Token Server按钮
选择对应ip应用,将其设为Token Server,并配置该 Token Server 的端口以及最大的 QPS 配额(用于限制资源使用,防止嵌入模式下影响应用本身)。接下来我们就在下面的选择框中为该 Token Server 分配 Token Client。选择完成后点击“保存”按钮保存分配。
保存成功后,我们就能在 Token Server 列表页面看到刚刚分配的 Token Server 了:
springboot项目中可以加入如下配置,来告诉sentinel针对哪些请求做限流拦截,其他web应用参考上面链接里的接入方式
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
//过滤器配置
registration.setFilter(new CommonFilter());
//请根据实际情况配置要拦截的 URL Pattern
registration.addUrlPatterns("*.json","*.hml","*.html","/demo/*");
registration.setName("sentinelCommonFilter");
registration.setOrder(1);
return registration;
}
}
CommonFilter为Sentinel封装好的限流的公用的过滤器,如果自己需要扩展,可以extends该类,并做特殊实现,addUrlPatterns方法指明针对哪些请求做过滤
registration.addUrlPatterns("*.json","*.hml","*.html","/demo/*");
上诉配置完后,就可以重启项目了
代码中模拟如下实现,假设FlowControlService,其调用的是第三方服务接口,我们在其需要流控的方法上添加@SentinelResource
注解,名称为限流资源名称
@Service
public class FlowControlService {
@SentinelResource("clusterFlowControl")
public int clusterFlowControlTest(int i) {
return i;
}
}
controller层代码如下
@GetMapping("flowControl")
public BaseResult flowControl() {
for (int i = 0; i < 10; i++) {
//mock接口调用
System.out.println(flowControlService.clusterFlowControlTest(i));
System.out.println("请求成功"+i);
}
System.out.println("请求成功");
return new BaseResult();
}
项目启动后,需要访问一次接口,才可以在云上控制台中看到自己的项目
访问一次controller中测试接口后,可以在控制台中看到如下日志数据:
代表sentinel初始化成功,同时,AHAS控制台中也能看到项目请求数据
先在本地启动2个一样的项目,端口分别为8080,8081,模拟项目集群部署,同时使用Jmeter不断请求2个项目中同一个接口来模拟负载均衡后的请求情况
假设不加任何流控规则,jmeter不断请求,qps一下就彪的很高,超过了10000,如图
在AHAS中新建流控规则,为了验证,集群流控是否有效,先建立单机均摊qps规则如下,阈值模式选均摊类型,即每台机器接口请求限制其qps为50,集群qps=50*2=100
再次使用jmter请求,qps请求数据如图,通过qps始终为100,请求不通过部分会报异常
为了测试集群流控效果,需要完成两点
在配置TokenServer,配置链接为
https://ahas.console.aliyun.com/#/SystemGuardClusterServerPage?appName=owner-front®ionId=public&_k=f9zjb1
选择一台机器作为TokenServer,并分配集群中其他机器为Token Client
再次使用jmeter请求,看下结果
可以看到qps被限制在了50,集群限流生效
个人觉得AHAS控制台集成集群流控,有如下优缺点
优点:
缺点
接下来会尝试接入开源Sentinel控制台,并整合Apollo配置中心,单独部署TokenServer实现集群流控,到时再做分享