sentinel小记

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、触发熔断

  • 请求一个不存在的值,触发异常熔断

  • 随后进入熔断降级操作,返回空对象

    • 正常请求也返回空对象
  • 但是我在熔断期间请求数频繁时又会触发限流,并且返回限流规则,无法返回降级规则

    • 这里可知,限流的优先级是要高于熔断的,并且两个规则是独立的。

相关推荐
步行cgn14 分钟前
Spring MVC POST 请求乱码:原因与完整解决方案
java·spring·mvc
y1su15 分钟前
Leetcode 链表,树,回溯 模板
java·leetcode·链表
qianyuqiye120 分钟前
K8s 命名空间与 Pod 入门:从概念到实战
java·docker·kubernetes
牧瀬クリスだ28 分钟前
观察者模式:一个对象变化,一群对象自动响应
java·观察者模式·设计模式
小张成长计划..31 分钟前
【Linux】26:线程互斥和同步
java·开发语言
邪修king3 小时前
Re:Linux 系统篇(三十五):进程间通信Chapter2:从匿名管道到进程池:Linux 进程间通信实战(深度理解「先描述,再组织」)
java·linux·运维
拆房老料4 小时前
【第四部分:Agentic 智能体设计模式】16. 一个 Prompt 搞不定复杂任务?试试 Prompt Chaining
java·前端·人工智能·设计模式·prompt
张张123y4 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
曹牧9 小时前
C#:空合并运算符
java·前端·数据库
布吉岛的石头9 小时前
Java 程序员第 50 阶段2:预训练的目标函数:自回归语言建模本质
java·开发语言·人工智能·深度学习·回归·transformer