当访问量过大,超出系统可能承受的范围时,就会把整个系统压垮。限流就是限制请求数量,以保障系统稳定。
定义限流资源
和熔断一样,先定义一个要被限流的资源。
@SentinelResource(value = "hello")
@RequestMapping("/hello")
public String hello() throws Exception {
Thread.sleep(10);
return "业务处理";
}
并发限流规则
每秒之内,当hello资源的并发请求数达到10,就会触发限流。即第11个请求开始全部会被拒绝,抛出FlowException异常。
@PostConstruct
private void initFlowRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("hello"); //保护资源名
rule.setCount(10); //并发数
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); //策略为QPS并发
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
也可以修改策略,根据并发线程数来限流。一个请求耗时可能只需要几毫秒,在1秒之内,一个线程处理完这个请求后,马上可以继续处理更多N个请求,其占用的并发线程数是1。
rule.setGrade(RuleConstant.FLOW_GRADE_THREAD); //策略为线程并发
Warm Up预热模式
当请求量从较低的数量突然变得很大时,有时可能希望给系统一个逐步适应的预热过程。比如限流数为10,预热时间10秒,突然每秒都会收到100个语法,可能第一秒只接收3-5个请求,第二秒4-6个等,每秒逐步递增,直到10秒后,会稳定接收10个请求。
FlowRule rule = new FlowRule();
rule.setResource("hello");
rule.setCount(10);
rule.setGrade(RuleConstant.GRADE_QPS);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP); //预热控制行为
rule.setWarmUpPeriodSec(10); //预热时间为10秒
匀速排队模式
可能在某一时点请求特别大,比如秒杀。系统无法及时处理,但是可以放在队列中,每间隔一定时间,匀速逐个处理。如下,假如瞬间有100个请求,而我们每秒处理极限是10,排除时间是10秒,那么系统每100毫秒只会接收1个请求。并且预估在排队时间内能否完成剩余请求,能完成的就去排队,不能完成的就直接拒绝。这里理论上,10秒之内会匀速完成全部100个请求。
rule.setGrade(RuleConstant.GRADE_QPS);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER); //匀速排队模式
rule.setCount(10);
rule.setMaxQueueingTimeMs(10 * 1000);//排队时间为10秒
限流处理
和熔断类似,限流后会抛出FlowException异常,可在spring全局异常处理类中捕捉处理,也可单独处理。配置blockHandler对应的方法即可.
@SentinelResource(value = "hello", blockHandler = "blockHandler")
@RequestMapping("/hello")
public String hello() throws Exception {
Thread.sleep(10);
return "业务处理";
}
public String blockHandler(BlockException e) {
return "发生限流";
}
blockHandler指定的方法返回类型和参数必须和原方法一致,只能多加一个BlockException e参数,用于接收异常。也可以通过blockHandlerClass指定一个类来处理,将blockHandler的方法放在类中,类中的方法必须是静态的。