SpringCloud--Sentinel使用

一、快速开始

Sentinel 的使用可以分为两个部分:

  • 核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。
1.1、客户端引入 Spring Cloud Alibaba Sentinel 依赖

在客户端 Spring Boot 项目的pom.xml文件中添加Sentinel的依赖。

bash 复制代码
	<!-- Sentinel 核心依赖 -->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-core</artifactId>
        <version>最新版本号</version>
    </dependency>
    <!-- Spring Boot 集成 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        <version>最新版本号</version>
    </dependency>
1.2、启动 Sentinel Dashboard

Sentinel Dashboard是一个可视化的控制台,用于查看流量数据和管理规则。可以从GitHub上下载最新版本的控制台 jar 包再通过命令将其启动。或者也可以下载 Sentinel 控制台源码自行构建运行。

bash 复制代码
1.下载地址:
https://github.com/alibaba/Sentinel/releases

2.启动命令,-Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

3.启动成功后,在浏览器中输入 http://localhost:8080 打开控制台。

4.输入默认的用户名和密码都是 sentinel进行登录。
1.3、配置客户端连接到 Sentinel Dashboard

在客户端项目的application.properties或application.yml配置文件中设置Sentinel Dashboard的地址。

bash 复制代码
spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: localhost:8080
1.4、定义资源

在客户端代码中,可以通过编程的方式调用 Sentinel 的 API 来定义资源。也可以通过@SentinelResource注解对某个方法进行标注成资源。

(1)API 方式:

bash 复制代码
@GetMapping("/example")
public String example() {
    // 定义资源名称
    String resource = "example";
    // 调用Sentinel API进行流量控制
    SphU.entry(resource, () -> {
        // 这里是你的业务逻辑
        return "Hello Sentinel";
    });
    return "success";
}

(2)注解方式:

bash 复制代码
@SentinelResource(value = "productDetails", blockHandler = "blockHandler")
public ProductDetails getProductDetails(String productId) {
    // 业务逻辑
}
1.5、配置规则

在Sentinel Dashboard控制台中进行图形化配置规则。进入控制台后,选择左侧菜单栏的具体规则菜单,然后点击右上方"新增"按钮来定义规则。也可以通过编程方式动态添加GatewayFlowRule到Sentinel的规则仓库中。

(1)控制台图形化配置:

(2)编程式动态添加:

bash 复制代码
public class RuleConfig {
    public static void main(String[] args) {
        // 创建一个限流规则
        FlowRule rule = new FlowRule();
        rule.setResource("product_route"); // 设置资源名称
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 设置限流策略等级为QPS
        rule.setCount(10); // 设置每秒最大请求数为10

        // 将规则添加到内存中
        GatewayRuleManager.loadRules(Collections.singletonList(rule));
    }
}

二、简单使用实例

通过@SentinelResource注解将需要使用 Sentinel 进行控制的方法定义成资源,后续对该方法的访问都会受到Sentinel 所配置的相关规则控制。

bash 复制代码
@RestController
public class TestController {

    @Autowired
    private TestService service;

    @GetMapping(value = "/hello/{name}")
    public String apiHello(@PathVariable String name) {
        return service.sayHello(name);
    }
}

@Service
public class TestService {

    @SentinelResource(value = "sayHello")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}
2.1 @SentinelResource 注解

@SentinelResource 注解用来标识资源是否被限流、降级。该注解有如下属性:

  • value:资源名称,必需项(不能为空)。
  • entryType:entry 类型,可选项(默认为 EntryType.OUT)。
  • blockHandler:blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数签名和位置要求:
    • 函数访问范围需要是 public,返回类型需要与原方法相匹配;
    • 方法参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException;
    • blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析;
  • fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
    • 函数访问范围需要是 public,返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常;
    • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析;
  • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求与fallback一样。
  • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

示例:

bash 复制代码
public class TestService {
    // 原函数
    @SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
    public String hello(long s) {
        return String.format("Hello at %d", s);
    }
    
    // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
    public String helloFallback(long s) {
        return String.format("Halooooo %d", s);
    }

    // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
    public String exceptionHandler(long s, BlockException ex) {
        // Do some log here.
        ex.printStackTrace();
        return "Oops, error occurred at " + s;
    }
}
2.2 注解埋点使用限制
  • 确保项目引入了 Spring AOP(或相关 starter)
  • 确保注解方法所在的类已注册为 Spring bean,非 Spring bean 不支持
  • 注意注解埋点不支持 private 方法,不支持内部调用
  • static 方法受 AOP 限制,无法进行代理,暂不支持
  • 若 blockHandler/fallback 不生效,则排查函数签名是否符合要求
  • 如果是不支持 AOP 的场景(比如 javax WebSocket),则无法使用注解方式埋点,需要使用 SphU 方式埋点

三、Spring Cloud Gateway 支持

3.1 引入相关依赖

若想让Spring Cloud Gateway 跟 Sentinel Starter 配合使用,需要加上 spring-cloud-alibaba-sentinel-gateway 依赖,同时需要添加 spring-cloud-starter-gateway 依赖来让 spring-cloud-alibaba-sentinel-gateway 模块里的 Spring Cloud Gateway 自动化配置类生效。

bash 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
3.2 Sentinel 对 Spring Cloud Gateway 进行限流

在Spring Cloud Gateway中,SentinelGatewayFilter作为一个全局过滤器被集成进来,用于拦截流经网关的请求,并应用Sentinel的流量控制规则。Sentinel 提供了 Spring Cloud Gateway 两种资源维度的限流,默认的粒度是 route 维度以及自定义 API 分组维度。默认不支持 URL 粒度,所以需要将 spring.cloud.sentinel.filter.enabled 配置项置为 false。

  • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
  • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

使用时首先需引入以下模块:

bash 复制代码
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>

然后再注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。

bash 复制代码
@Configuration
public class GatewayConfiguration {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
}
3.3 自定义SentinelGatewayFilter

如果需要自定义流量控制逻辑,可以创建一个自定义的SentinelGatewayFilter实现类。通常涉及以下步骤:

  1. 添加依赖:首先,确保你的项目中已经加入了Sentinel的相关依赖。
  2. 启用Sentinel:在你的Spring Boot应用中添加@EnableSentinel注解来开启Sentinel。
  3. 创建自定义过滤器:创建一个实现GlobalFilter接口的类。这个接口用于定义过滤器的名称、描述和执行逻辑。
  4. 注入SentinelGatewayFilter:在你的自定义过滤器中注入SentinelGatewayFilter,以便能够调用Sentinel的处理逻辑。
  5. 实现过滤逻辑:在实现类中,覆盖apply方法,在其中编写具体的过滤逻辑。
  6. 注册过滤器:将自定义的GlobalFilter实现类作为Bean注册到Spring应用上下文中。

示例:

bash 复制代码
/**
 * 创建自定义过滤器
 **/
@Component
public class CustomSentinelGatewayFilter implements GlobalFilter, Ordered {

    private final SentinelGatewayFilter sentinelGatewayFilter;
	
	// 注入SentinelGatewayFilter
    public CustomSentinelGatewayFilter(SentinelGatewayFilter sentinelGatewayFilter) {
        this.sentinelGatewayFilter = sentinelGatewayFilter;
    }

	/**
 	* 实现自定义过滤逻辑
 	**/
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            // 在执行Sentinel的过滤逻辑之前,可以添加自定义的预处理逻辑
            // ...

            // 执行Sentinel的过滤逻辑
            return sentinelGatewayFilter.filter(exchange, chain);

        } catch (BlockException ex) {
            // 当Sentinel拦截请求时,可以在这里添加自定义的处理逻辑
            // ...
            return Mono.empty();
        }
    }

    @Override
    public int getOrder() {
        // 设置过滤器的执行顺序,数值越小越先执行
        return SentinelGatewayFilter.ORDER - 1;
    }
}

在Spring Boot的配置类中注册自定义过滤器。

bash 复制代码
@Configuration
public class GatewayConfig {

    @Bean
    public GlobalFilter customFilter() {
        return new CustomSentinelGatewayFilter(new SentinelGatewayFilter());
    }
}
相关推荐
浏览器爱好者3 小时前
谷歌浏览器的网络安全检测工具介绍
chrome·安全
益达是我4 小时前
【Chrome】浏览器提示警告Chrome is moving towards a new experience
前端·chrome
catmes5 小时前
设置浏览器声音或视频的自动播放策略
chrome·音视频·edge浏览器
feifeiyechuan7 小时前
【Chrome Extension】二、导航栏快速查询
前端·chrome·chromeextension
代码的乐趣9 小时前
支持selenium的chrome driver更新到131.0.6778.204
chrome·python·selenium
路人甲ing..11 小时前
jupyter切换内核方法配置问题总结
chrome·python·jupyter
搬码后生仔12 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
小马哥编程21 小时前
原型链(Prototype Chain)入门
css·vue.js·chrome·node.js·原型模式·chrome devtools
荆州克莱1 天前
mysql中局部变量_MySQL中变量的总结
spring boot·spring·spring cloud·css3·技术
金创想1 天前
chrome主页被被篡改的修复方法
chrome·主页篡改