废话
其实大部分人都是苦于不知道用啥工具去做限流,如果自己写一个限流逻辑,似乎又比较low,所以,当看到我这个标题的时候,其实本章大概率是不需要再去看了。
建议直接看官方文档吧,写得挺清楚的:https://github.com/alibaba/Sentinel
我这里就做一个最简单的限流示例,规则是每秒1次请求,超出1次就返回请求过于频繁的提示。
概述
Sentinel支持两种模式,1种是简单的导个包,跑限流策略,另外一种是可以安装一个他提供的管理后台,提供了不少比较丰富的(花里胡哨)的功能,我这里图省事,搞第一种就好。
有些人会比较关心另外一个问题,就是集群限流功能,大一点的业务量不可能只有一个Gateway,Gateway之间的内存肯定也无法共享,如果是接入Redis做计数,肯定也会有资源、时间成本等问题。我个人的看法,解决集群限流的问题可以从两个方面着手:
(1)统一计数中心,例如搞个Redis做计数,范围时间内超了就拒绝,也就是会面临时间、资源成本。当然了,Sentinel提供了这种能力,秉承着无需重复造*的初衷,我选择相信它能比我自己处理的要好。
(2)负载均衡策略调整,如Nginx可支持根据来源IP地址做负载均衡规则,确保每一个IP的请求都指向同一个Gateway,这样也有风险,当你运气实在是不好的时候,就可能出现某个Gateway忙不过来,而某个Gateway却无人问津。
现实总是这样,很难有完美的东西,总是会在不同的选择之间妥协。
开搞
导包
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.0</version>
</dependency>
最简单的示例
@Override
public void run(String... args) throws Exception {
log.info("初始化");
initFlowRules();
while (true) {
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
/*您的业务逻辑 - 开始*/
log.info("hello world");
/*您的业务逻辑 - 结束*/
} catch (BlockException e1) {
/*流控逻辑处理 - 开始*/
log.info("被限流了");
/*流控逻辑处理 - 结束*/
} finally {
if (entry != null) {
entry.exit();
}
}
}
}
private static void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// Set limit QPS to 20.
rule.setCount(1);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
这个run等同于main,运行没错的话,大概率就是没秒打印1个hello world,以及n个被限流了,如果把“被限流了”注释掉,就会每秒打印一个hello world。
真正用上的时候,另起一个Gateway过滤器,把HelloWorld换成你的用户Token或者其他用于限频的凭证即可。