Sentinel-服务保护(限流、熔断降级)

目录

Sentinel-基础-工作原理

功能介绍

架构原理

资源&规则

定义资源:

定义规则:

工作原理

Sentinel-整合-基础场景

整合使用

定义资源

添加规则

sentinel-异常处理-Web接口

sentinel-异常处理-@SentinelResource

一、核心概念

[二、@SentinelResource 核心属性(异常处理重点)](#二、@SentinelResource 核心属性(异常处理重点))

三、实操示例

[1. 前置准备](#1. 前置准备)

[2. 基础使用:配置 blockHandler(处理限流 / 熔断异常)](#2. 基础使用:配置 blockHandler(处理限流 / 熔断异常))

测试方式:

四、关键注意事项

sentinel-异常处理-openfeign调用

[sentinel-异常处理-SphU 硬编码](#sentinel-异常处理-SphU 硬编码)

Sentinel-基础-工作原理

功能介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。SpringcloudAlibabasentinel以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。

架构原理

资源&规则

定义资源:

  • 主流框架自动适配(Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor);
  • 所有Web接口均为资源
  • 编程式:SphUAPI
  • 声明式:@SentinelResource

定义规则:

  • 流量控制(FlowRule)
  • 熔断降级(DegradeRule)
  • 系统保护(SystemRule)
  • 来源访问控制(AuthorityRule)
  • 热点参数(ParamFlowRule)

工作原理

Sentinel-整合-基础场景

整合使用

下载sentinel控制台:https://github.com/alibaba/Sentinel/releases/tag/1.8.8

下载完成之后,在路径中输入cmd,然后输入

复制代码
java -jar sentinel-dashboard-1.8.8.jar

如下图所示,sentinel启动成功:

启动成功之后,访问Sentinel Dashboard,账号密码都是sentinel:

登录成功页面如下:

在services的pom文件中引入sentinel依赖:

复制代码
        <!--        导入sentinel依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

引入完成之后,每一个微服务都需要配置连接上sentinel控制台:

订单服务:在配置文件中添加:

复制代码
    sentinel:
      transport:
        dashboard: locallhost:8080
      eager: true

商品服务:

复制代码
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.eager=true

重启服务,刷新sentinel控制台,发现控制台中已有order-service和product-service。

定义资源

1.假设在订单服务中,我们认为createOrder是一个资源,一个最简单的方法就是在该方法上面添加

复制代码
@SentinelResource(value = "createOrder")注解。

2.重启订单服务。

3.在前端发送createOrder请求:http://localhost:8000/create?userId=2&productId=4

4.请求返回成功之后,查看sentinel控制台的service的簇点链路。

6.有了这些资源,就可以对这些资源进行流控、熔断、热点、授权的控制。

添加规则

假设对/create添加流控规则

点击新增,在流控规则栏就可以看到添加的规则

重启服务,访问/create,访问请求过快时,则会出现以下错误。

上述现象可以,当访问访问请求过快时,会自动返回提示。接下来看sentinel的异常处理

sentinel-异常处理-Web接口

我们要使当请求违反规则时,返回的数据按照我们想要的方式返回,就需要重写一个异常处理器。首先在service-order中添加一个MyBlockExceptionHandle类。

复制代码
package com.atguigu.order.exception;

import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.PrintWriter;
@Component
public class MyBlockExceptionHandle implements BlockExceptionHandler {
    /**
     * 这是springMVC框架底层整合的jackson,提供的一个json工具
     */
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void handle(HttpServletRequest httpServletRequest,
                       HttpServletResponse httpServletResponse,
                       String s,
                       BlockException e) throws Exception {
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter writer = httpServletResponse.getWriter();
        R error = R.error(s + "被sentinel限制了,原因是:" + e.getMessage());
        String json = objectMapper.writeValueAsString(error);
        writer.write(json);
    }
}

然后我们需要在model下定义一个统一返回结果的类:

复制代码
package com.atguigu.common;

import lombok.Data;

@Data
public class R {
    private String code;
    private String message;
    private Object data;

    public static R ok() {
        R r = new R();
        r.setCode("200");
        r.setMessage("操作成功");
        return r;
    }

    public static R ok(Object data) {
        R r = new R();
        r.setCode("200");
        r.setMessage("操作成功");
        r.setData(data);
        return r;
    }

    public static R error() {
        R r = new R();
        r.setCode("500");
        r.setMessage("操作失败");
        return r;
    }

    public static R error(String message) {
        R r = new R();
        r.setCode("500");
        r.setMessage(message);
        return r;
    }


}

重启项目,多次访问/create,发现返回的是我们想要的格式:

sentinel-异常处理-@SentinelResource

一、核心概念

1.@SentinelResource 是什么?

@SentinelResource 是什么? 它是 Sentinel 提供的注解式资源定义方式 ,用于标记一个「受 Sentinel 保护的资源」(比如一个方法、一个接口)。通过这个注解,你可以脱离 Sentinel 原生的硬编码方式(SphU.entry()/exit()),更优雅地实现资源的限流、熔断、降级,同时还能自定义异常处理逻辑。

2.核心作用(异常处理相关)

  • 标记受保护资源,让 Sentinel 能够对该资源进行流量控制和熔断监控。
  • 自定义限流 / 熔断后的兜底处理逻辑(而非直接返回 Sentinel 默认的错误页面 / 信息)。
  • 区分业务异常Sentinel 限流 / 熔断异常,避免二者混淆。

二、@SentinelResource 核心属性(异常处理重点)

注解中有几个核心属性,重点关注和异常处理相关的:

属性名 作用 是否必填 备注
value 资源名称(唯一标识,Sentinel 控制台展示的资源名) 必须指定唯一值,用于区分不同资源
blockHandler 限流 / 熔断后的兜底方法名 (处理 Sentinel 定义的 BlockException 及其子类) 兜底方法需满足「同参数、同返回值、与原方法在同一个类中」,可额外添加 BlockException 入参
blockHandlerClass 兜底方法所在的类(当兜底方法不在原方法所在类时使用) 兜底方法必须是静态方法 ,且满足「同参数、同返回值、可额外加 BlockException 入参」
fallback 处理业务异常 (非 BlockException)的兜底方法名 兜底方法需满足「同返回值、参数列表与原方法一致,或额外添加 Throwable 入参」
fallbackClass 业务异常兜底方法所在的类 兜底方法必须是静态方法 ,规则同 fallback
exceptionsToIgnore 需要忽略的异常类型(不触发 fallback 例如 NullPointerException.class,忽略后该异常不会进入 fallback 方法

关键区分:BlockException 是 Sentinel 自身抛出的异常(包含限流、熔断、系统保护等场景),只有它会触发 blockHandler ;而普通业务异常(如 NullPointerExceptionIllegalArgumentException)会触发 fallback(若配置)。

三、实操示例

1. 前置准备

先引入 Sentinel 核心依赖(Spring Boot 项目),确保项目能正常集成 Sentinel:

复制代码
<!-- Spring Cloud Alibaba Sentinel 核心依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <!-- 版本需与 Spring Cloud Alibaba 版本匹配,例如 2021.0.1.0 -->
    <version>2021.0.1.0</version>
</dependency>

2. 基础使用:配置 blockHandler(处理限流 / 熔断异常)

这是最常用的场景,实现「资源被限流 / 熔断后,返回自定义兜底响应」。

复制代码
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SentinelDemoController {

    // 标记受保护资源,配置 blockHandler 兜底方法
    @GetMapping("/hello")
    @SentinelResource(value = "helloResource", blockHandler = "helloBlockHandler")
    public String hello(@RequestParam(required = false, defaultValue = "guest") String name) {
        // 正常业务逻辑
        return "Hello, " + name + "!";
    }

    // 限流/熔断兜底方法:满足 同参数、同返回值、额外可加 BlockException
    public String helloBlockHandler(String name, BlockException e) {
        // 自定义兜底响应,可打印异常信息排查问题
        System.err.println("资源【helloResource】被限流/熔断,异常类型:" + e.getClass().getSimpleName());
        return "抱歉,当前访问人数过多,请稍后再试!";
    }
}

测试方式:

  1. 启动项目,访问 http://localhost:8080/hello?name=test,正常返回 Hello, test!
  2. 启动 Sentinel 控制台(需提前下载并启动),在「流量控制规则」中给 helloResource 添加一条限流规则(例如:QPS 阈值 = 1,即每秒最多允许 1 次访问)。
  3. 快速多次访问 http://localhost:8080/hello,触发限流,会返回兜底信息 抱歉,当前访问人数过多,请稍后再试!,同时控制台会打印异常类型(FlowException,即限流异常)。

四、关键注意事项

  1. 兜底方法的签名规则
    • blockHandler 方法:必须与原方法参数列表一致 ,返回值一致,可额外添加 BlockException 入参(用于获取异常详情)。
    • fallback 方法:必须与原方法返回值一致 ,参数列表可一致,或额外添加 Throwable 入参(用于获取业务异常详情)。
    • 抽离到单独类时,兜底方法必须是 **public static** 修饰。
  2. 异常优先级
    • 当方法同时抛出 BlockException 和业务异常时,blockHandler 优先级高于 fallback(即 Sentinel 异常优先处理)。
    • exceptionsToIgnore 配置的异常,不会触发 fallback 方法,会直接向上抛出。
  3. 资源名唯一性
    • value 属性是资源的唯一标识,Sentinel 控制台的规则配置、监控数据都依赖该名称,建议命名规范(如 接口名:方法名)。
  4. 注解生效条件
    • 确保项目中已启用 Sentinel 注解支持(Spring Boot 项目中,引入 spring-cloud-starter-alibaba-sentinel 后会自动启用,无需额外配置;非 Spring Boot 项目需手动配置 SentinelResourceAspect)。

sentinel-异常处理-openfeign调用

在前面openfeign文章中已讲解。

sentinel-异常处理-SphU 硬编码

这种异常处理的方法就是try-catch方法包围即可。

相关推荐
源力祁老师1 小时前
深入解析 Odoo 中 default_get 方法的功能
java·服务器·前端
NWU_白杨2 小时前
多线程安全与通信问题
java
sheji34162 小时前
【开题答辩全过程】以 工业车辆维修APP设计与实现为例,包含答辩的问题和答案
java
虫小宝2 小时前
淘客系统的容灾演练与恢复:Java Chaos Monkey模拟节点故障下的服务降级与快速切换实践
java·开发语言
zz34572981132 小时前
c语言基础概念9
c语言·开发语言
yxm26336690812 小时前
【洛谷压缩技术续集题解】
java·开发语言·算法
键盘帽子2 小时前
多线程情况下长连接中的session并发问题
java·开发语言·spring boot·spring·spring cloud
毅炼2 小时前
Java 基础常见问题总结(1)
开发语言·python
无名-CODING2 小时前
Spring事务管理完全指南:从零到精通(上)
java·数据库·spring