sentinel_0">sentinel小记
1、被处理的接口
-
java">/** * 分页获取题目列表(封装类) * * @param questionQueryRequest * @param request * @return */ @PostMapping("/list/page/vo") public BaseResponse<Page<QuestionVO>> listQuestionVOByPage(@RequestBody QuestionQueryRequest questionQueryRequest, HttpServletRequest request) { long current = questionQueryRequest.getCurrent(); long size = questionQueryRequest.getPageSize(); // 限制爬虫,限制每页最多 20 条数据 ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); //对ip进行限流 String ip = request.getRemoteAddr(); Entry entry = null; try { entry = SphU.entry("listQuestionVOByPage", EntryType.IN, 1, ip); //被保护的用户 // 查询数据库 Page<Question> questionPage = questionService.page(new Page<>(current, size), questionService.getQueryWrapper(questionQueryRequest)); // 获取封装类 return ResultUtils.success(questionService.getQuestionVOPage(questionPage, request)); } catch (Throwable ex) { // 处理业务异常 if (!BlockException.isBlockException(ex)){ Tracer.trace(ex); return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误"); } if (ex instanceof DegradeException) { // 降级操作 return handleFallback(questionQueryRequest, request, ex); } // 限流操作 return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "访问过于频繁,情稍后再试"); } finally { if (entry != null) { entry.exit(1, ip); } } } /** * listQuestionBankVOByPage 降级操作:直接返回本地数据 * 处理的是业务本身的异常 */ public BaseResponse<Page<QuestionVO>> handleFallback(@RequestBody QuestionQueryRequest questionQueryRequest, HttpServletRequest request, Throwable ex) { // 可以返回本地数据或空数据 return ResultUtils.success(null); }
2、熔断和限流规则例子
-
java">/** * @author zzj * 限流规则管理器 */ @Component public class SentinelRulesManager { @PostConstruct public void initRules() { initFlowRules(); initDegradeRules(); } // 限流规则 public void initFlowRules() { // 单 IP 查看题目列表限流规则 ParamFlowRule rule = new ParamFlowRule("listQuestionVOByPage") .setParamIdx(0) // 对第 0 个参数限流,即 IP 地址 .setCount(60) // 每分钟最多 60 次 .setDurationInSec(60); // 规则的统计周期为 60 秒 ParamFlowRuleManager.loadRules(Collections.singletonList(rule)); } // 降级规则 public void initDegradeRules() { // 单 IP 查看题目列表熔断规则 DegradeRule slowCallRule = new DegradeRule("listQuestionVOByPage") .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()) .setCount(0.2) // 慢调用比例大于 20% .setTimeWindow(60) // 熔断持续时间 60 秒 .setStatIntervalMs(30 * 1000) // 统计时长 30 秒 .setMinRequestAmount(10) // 最小请求数 .setSlowRatioThreshold(3); // 响应时间超过 3 秒 DegradeRule errorRateRule = new DegradeRule("listQuestionVOByPage") .setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType()) .setCount(0.1) // 异常率大于 10% .setTimeWindow(60) // 熔断持续时间 60 秒 .setStatIntervalMs(30 * 1000) // 统计时长 30 秒 .setMinRequestAmount(10); // 最小请求数 // 加载规则 DegradeRuleManager.loadRules(Arrays.asList(slowCallRule, errorRateRule)); } }
3、正常请求—>限流
-
当请求到61次时,进行限流
-
-
4、触发熔断
-
请求一个不存在的值,触发异常熔断
-
-
随后进入熔断降级操作,返回空对象
-
正常请求也返回空对象
-
-
-
但是我在
熔断期间请求数频繁时
又会触发限流,并且返回限流规则,无法返回降级规则-
-
这里可知,限流的优先级是要高于熔断的,并且两个规则是独立的。
-