Spring Cloud Alibaba Sentinel集成

Posted java_wxid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Alibaba Sentinel集成相关的知识,希望对你有一定的参考价值。

创建spring-cloud-alibaba-sentinel-demo项目

项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/spring-cloud-alibaba-sentinel-demo
项目结构如下(示例):

修改pom.xml

代码如下(示例):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <groupId>com.example</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-alibaba-sentinel-demo</name>
    <description>Demo project for Spring Boot</description>

    <!--    属性配置-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <!--引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
        在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系-->
        <spring.boot.version>2.3.12.RELEASE</spring.boot.version>
        <spring.cloud.version>Hoxton.SR12</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.7.RELEASE</spring.cloud.alibaba.version>
    </properties>

    <dependencies>
        <!--        代表web模块,在这个模块中含了许多JAR包,有spring相关的jar,内置tomcat服务器,jackson等,这些web项目中常用的的功能都会自动引入-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.4.1</version>
        </dependency>

        <!--        druid驱动-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.23</version>
        </dependency>
        <!--        mysql连接-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!--        mybatis的一个库-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>

        <!-- Alibaba Nacos 配置 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--        在SpringBoot 2.4.x的版本之后,对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持,其实这个jar包里什么都没有,就只有一个标识类Marker,用来标识要开启Bootstrap配置文件的支持,由于父类用了2.5.6版本需要导入如下的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.0</version>
        </dependency>

        <!--openfeign客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-openfeign-core</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--引入HttpClient依赖-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
        <!-- 引入Feign Slf4j -->
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-slf4j</artifactId>
            <version>8.14.4</version>
        </dependency>
        <!--        lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>


<!--        @SentinelResource 注解用来标识资源是否被限流、降级。

        blockHandler: 定义当资源内部发生了BlockException应该进入的方法(捕获的是Sentinel定义的异常)
        fallback: 定义的是资源内部发生了Throwable应该进入的方法
        exceptionsToIgnore:配置fallback可以忽略的异常
        源码入口:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.0</version>
        </dependency>

<!--        流控规则设置可以通过Sentinel dashboard配置
        客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
            <version>1.8.0</version>
        </dependency>

        <!--- 解决流控链路不生效的问题
        从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,导致链路限流不生效。
        从1.7.0版本开始,官方在CommonFilter引入了WEB_CONTEXT_UNIFY参数,用于控制是否收敛context,将其配置为false即可根据不同的URL进行链路限流。
        1.8.0 需要引入sentinel-web-servlet依赖
        -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
        </dependency>

        <!-- Spring Cloud Alibaba整合Sentinel -->

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--sentinel持久化 采用 Nacos 作为规则配置数据源-->
<!--        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>-->
    </dependencies>


    <!--
        引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
        在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系
     -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>$spring.boot.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>$spring.cloud.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>$spring.cloud.alibaba.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

修改SpringCloudAlibabaSentinelDemoApplication

代码如下(示例):

package com.example.springcloudalibabasentineldemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@MapperScan("com.example.springcloudalibabasentineldemo.dao")
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SpringCloudAlibabaSentinelDemoApplication 

    public static void main(String[] args) 
        SpringApplication.run(SpringCloudAlibabaSentinelDemoApplication.class, args);
    




创建bootstrap.yml

代码如下(示例):

#bootstrap.yml优先级比application.yml优先级高
spring:
  #prefix−spring.profile.active.$file-extension
  #nacos会根据当前环境去拼接配置名称查找相应配置文件,
  #示例:spring.application.name-spring.profiles.active-spring.cloud.nacos.config.file-extension
  #获取到值:nacos-autoconfig-service-dev.yml
  profiles:
    #开发环境dev,测试环境test,生产环境prod
    active: dev
  application:
    #配置应用的名称,用于获取配置
    name: spring-cloud-alibaba-sentinel-demo
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 106.14.132.94:8848
      config:
        #nacos配置中心地址
        server-addr: 106.14.132.94:8848
        #配置中心的命名空间id
        namespace: 9e50b6d9-6c3d-4e7a-b701-10f085e4b98d
        #配置分组,默认没有也可以
        group: DEFAULT_GROUP
        #配置文件后缀,用于拼接配置配置文件名称,目前只支持yaml和properties
        file-extension: yaml
        #配置自动刷新
        refresh-enabled: true
        #配置文件的前缀,默认是application.name的值,如果配了prefix,就取prefix的值
        #prefix: nacos-autoconfig-service-$spring.profile.active
        # 配置编码
        encode: UTF-8
        username: nacos
        password: nacos


创建application.yml

代码如下(示例):

server:
  port: 8095
#暴露actuator端点   http://localhost:8800/actuator/sentinel
management:
  endpoints:
    web:
      exposure:
        include: '*'
spring:
  application:
    name: mall-user-sentinel-demo
  cloud:
    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 127.0.0.1:8080
        # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
        #port: 8719
  #      datasource:
  #        ds1:
  #          nacos:
  #            server-addr: 127.0.0.1:8848
  #            dataId: $spring.application.name
  #            groupId: DEFAULT_GROUP
  #            data-type: json
  #            rule-type: flow
  #数据库配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://139.224.137.74:3306/syncdemo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: ca0a997ee4770063
#mybatis
mybatis-plus:
  mapper-locations: classpath*:/mapper/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.example.springcloudalibabasentineldemo.entity







创建SentinelConfig

代码如下(示例):

package com.example.springcloudalibabasentineldemo.config;


import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import com.example.springcloudalibabasentineldemo.sentinel.MyUrlBlockHandler;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @className: SentinelConfig
 * @description: https://github.com/alibaba/Sentinel/issues/1213
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@Configuration
public class SentinelConfig 

    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() 
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        // 入口资源关闭聚合  解决流控链路不生效的问题
        registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
        registration.setName("sentinelFilter");
        registration.setOrder(1);

        //CommonFilter的BlockException自定义处理逻辑
        WebCallbackManager.setUrlBlockHandler(new MyUrlBlockHandler());

        //解决授权规则不生效的问题
        //com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser
        //WebCallbackManager.setRequestOriginParser(new MyRequestOriginParser());

        return registration;
    



创建HelloController

代码如下(示例):

package com.example.springcloudalibabasentineldemo.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@RestController
@Slf4j
public class HelloController 

    private static final String RESOURCE_NAME = "hello";

    @RequestMapping(value = "/hello")
    public String hello() 

        Entry entry = null;
        try 
            // 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
            entry = SphU.entry(RESOURCE_NAME);
            // 被保护的业务逻辑
            String str = "hello world";
            log.info("====="+str+"=====");
            return str;
         catch (BlockException e1) 
            // 资源访问阻止,被限流或被降级
            //进行相应的处理操作
            log.info("block!");
            return "被流控了!";
         catch (Exception ex) 
            // 若需要配置降级规则,需要通过这种方式记录业务异常
            Tracer.traceEntry(ex, entry);
         finally 
            if (entry != null) 
                entry.exit();
            
        
        return null;
    

    /**
     * 定义流控规则
     */
    @PostConstruct
    private static void initFlowRules()
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        //设置受保护的资源
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则 QPS
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值
        // Set limit QPS to 20.
        rule.setCount(1);
        rules.add(rule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    

创建LimitFlowController

代码如下(示例):

package com.example.springcloudalibabasentineldemo.controller;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@RestController
public class LimitFlowController 

    @RequestMapping("/test")
//    @SentinelResource(value = "test",blockHandlerClass = CommonBlockHandler.class,blockHandler = "handleException3")
    public String test() 

        try 
            Thread.sleep(100);
         catch (InterruptedException e) 
            e.printStackTrace();
        

        return "========test()========";
    

    AtomicInteger atomicInteger = new AtomicInteger();

    @RequestMapping("/test2")
    public String test2() 
        atomicInteger.getAndIncrement();
        if (atomicInteger.get() % 2 == 0)
            //模拟异常和异常比率
            int i = 1/0;
        

        return "========test2()========";
    

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/test3")  //CommonFilter
    public UserEntity test3() 
        UserEntity user = userService.getUser(1);
        return user;
    

    @RequestMapping(value = "/test4")
    public UserEntity test4() 
        UserEntity user = userService.getUser(1);
        return user;
    


    public String handleException(BlockException exception) 
        return "===被限流降级啦===";
    


创建UserController

代码如下(示例):

package com.example.springcloudalibabasentineldemo.controller;


import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.feign.OrderFeignService;
import com.example.springcloudalibabasentineldemo.sentinel.CommonBlockHandler;
import com.example.springcloudalibabasentineldemo.sentinel.CommonFallback;
import com.example.springcloudalibabasentineldemo.service.UserService;
import com.example.springcloudalibabasentineldemo.utils.PageUtils;
import com.example.springcloudalibabasentineldemo.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.Map;


/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@RestController
@RequestMapping(value = "/user")
public class UserController 
    @Autowired
    private UserService userService;

    @Autowired
    OrderFeignService orderFeignService;

    @RequestMapping(value = "/getNacosConfigure")
    @SentinelResource(value = "getNacosConfigure",
            blockHandlerClass = CommonBlockHandler.class,
            blockHandler = "getNacosConfigure",
            fallbackClass = CommonFallback.class,
            fallback = "getNacosConfigure"
    )
    public String getNacosConfigure() 
//        try 
//            // 模拟测试并发线程数限流
//            Thread.sleep(900);
//         catch (InterruptedException e) 
//            e.printStackTrace();
//        
        
        // findOrderByUserId  限流规则  2    sentinel dashboard 定义规则

        //feign调用
        String result = orderFeignService.getNacosConfigure();
        return result;
    


    /**
     * 列表
     */
    @RequestMapping("/list")
    @SentinelResource(value = "userlist",
            blockHandlerClass = CommonBlockHandler.class,
            blockHandler = "handleException",fallback = "fallback")
    public R list(@RequestParam Map<String, Object> params)
        PageUtils page = userService.queryPage(params);
       // int i=1/0;

        return R.ok().put("page", page);
    

    public R handleException(@RequestParam Map<String, Object> params,BlockException exception)
        return R.error(-1,"===被限流降级啦===");
    


    /**
     * 信息
     */
    @RequestMapping("/info/id")
    @SentinelResource(value = "userinfo",
            blockHandlerClass = CommonBlockHandler.class,
            blockHandler = "handleException2",
            fallbackClass = CommonFallback.class,
            fallback = "fallback"
    )
    public R info(@PathVariable("id") Integer id)
		UserEntity user = userService.getById(id);

		if(id==4)
		    throw new IllegalArgumentException("异常参数");
        

        return R.ok().put("mapper", user);
    

    public R handleException2(@PathVariable("id") Integer id, BlockException exception)
        return R.error(-1,"===被限流降级啦===");
    
    public R fallback(@PathVariable("id") Integer id,Throwable e)
        return R.error(-1,"===被熔断降级啦==="+e.getMessage());
    

    /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody UserEntity user)
		userService.save(user);
        return R.ok();
    

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody UserEntity user)
		userService.updateById(user);

        return R.ok();
    

    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Integer[] ids)
		userService.removeByIds(Arrays.asList(ids));

        return R.ok();
    



创建UserDao

代码如下(示例):

package com.example.springcloudalibabasentineldemo.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@Mapper
public interface UserDao extends BaseMapper<UserEntity> 
	


创建AuthorityDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;

import java.util.Collections;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class AuthorityDemo 
    private static final String RESOURCE_NAME = "testABC";

    public static void main(String[] args) 
        System.out.println("========Testing for black list========");
        initBlackRules();
        testFor(RESOURCE_NAME, "appA");
        testFor(RESOURCE_NAME, "appB");
        testFor(RESOURCE_NAME, "appC");
        testFor(RESOURCE_NAME, "appE");

        System.out.println("========Testing for white list========");
        initWhiteRules();
        testFor(RESOURCE_NAME, "appA");
        testFor(RESOURCE_NAME, "appB");
        testFor(RESOURCE_NAME, "appC");
        testFor(RESOURCE_NAME, "appE");
    

    private static void testFor(/*@NonNull*/ String resource, /*@NonNull*/ String origin) 
        ContextUtil.enter(resource, origin);
        Entry entry = null;
        try 
            entry = SphU.entry(resource);
            System.out.println(String.format("Passed for resource %s, origin is %s", resource, origin));
         catch (BlockException ex) 
            System.err.println(String.format("Blocked for resource %s, origin is %s", resource, origin));
         finally 
            if (entry != null) 
                entry.exit();
            
            ContextUtil.exit();
        
    

    private static void initWhiteRules() 
        AuthorityRule rule = new AuthorityRule();
        rule.setResource(RESOURCE_NAME);
        rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
        rule.setLimitApp("appA,appE");
        AuthorityRuleManager.loadRules(Collections.singletonList(rule));
    

    private static void initBlackRules() 
        AuthorityRule rule = new AuthorityRule();
        rule.setResource(RESOURCE_NAME);
        rule.setStrategy(RuleConstant.AUTHORITY_BLACK);
        rule.setLimitApp("appA,appB");
        AuthorityRuleManager.loadRules(Collections.singletonList(rule));
    


创建FlowThreadDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class FlowThreadDemo 

    private static AtomicInteger pass = new AtomicInteger();
    private static AtomicInteger block = new AtomicInteger();
    private static AtomicInteger total = new AtomicInteger();
    private static AtomicInteger activeThread = new AtomicInteger();

    private static volatile boolean stop = false;
    private static final int threadCount = 100;

    private static int seconds = 60 + 40;
    private static volatile int methodBRunningTime = 2000;

    public static void main(String[] args) throws Exception 
        System.out.println(
                "MethodA will call methodB. After running for a while, methodB becomes fast, "
                        + "which make methodA also become fast ");
        tick();
        initFlowRule();

        for (int i = 0; i < threadCount; i++) 
            Thread entryThread = new Thread(new Runnable() 
                @Override
                public void run() 
                    while (true) 
                        Entry methodA = null;
                        try 
                            TimeUnit.MILLISECONDS.sleep(5);
                            methodA = SphU.entry("methodA");
                            activeThread.incrementAndGet();
                            Entry methodB = SphU.entry("methodB");
                            TimeUnit.MILLISECONDS.sleep(methodBRunningTime);
                            methodB.exit();
                            pass.addAndGet(1);
                         catch (BlockException e1) 
                            block.incrementAndGet();
                         catch (Exception e2) 
                            // biz exception
                         finally 
                            total.incrementAndGet();
                            if (methodA != null) 
                                methodA.exit();
                                activeThread.decrementAndGet();
                            
                        
                    
                
            );
            entryThread.setName("working thread");
            entryThread.start();
        
    

    private static void initFlowRule() 
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource("methodA");
        // set limit concurrent thread for 'methodA' to 20
        rule1.setCount(20);
        rule1.setGrade(RuleConstant.FLOW_GRADE_THREAD);
        rule1.setLimitApp("default");

        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    

    private static void tick() 
        Thread timer = new Thread(new TimerTask());
        timer.setName("sentinel-timer-task");
        timer.start();
    

    static class TimerTask implements Runnable 

        @Override
        public void run() 
            long start = System.currentTimeMillis();
            System.out.println("begin to statistic!!!");

            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;

            while (!stop) 
                try 
                    TimeUnit.SECONDS.sleep(1);
                 catch (InterruptedException e) 
                
                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;

                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;

                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;
    
                System.out.println(seconds + " total qps is: " + oneSecondTotal);
                System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal
                        + ", pass:" + oneSecondPass
                        + ", block:" + oneSecondBlock
                        + " activeThread:" + activeThread.get());
                if (seconds-- <= 0) 
                    stop = true;
                
                if (seconds == 40) 
                    System.out.println("method B is running much faster; more requests are allowed to pass");
                    methodBRunningTime = 20;
                
            

            long cost = System.currentTimeMillis() - start;
            System.out.println("time cost: " + cost + " ms");
            System.out.println("total:" + total.get() + ", pass:" + pass.get()
                    + ", block:" + block.get());
            System.exit(0);
        
    


创建PaceFlowDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class PaceFlowDemo 
    private static final String KEY = "abc";

    private static volatile CountDownLatch countDown;

    private static final Integer requestQps = 100;
    private static final Integer count = 10;
    private static final AtomicInteger done = new AtomicInteger();
    private static final AtomicInteger pass = new AtomicInteger();
    private static final AtomicInteger block = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException 
        System.out.println("pace behavior");
        countDown = new CountDownLatch(1);
        initPaceFlowRule();
        simulatePulseFlow();
        countDown.await();

        System.out.println("done");
        System.out.println("total pass:" + pass.get() + ", total block:" + block.get());

        System.out.println();
        System.out.println("default behavior");
        TimeUnit.SECONDS.sleep(5);
        done.set(0);
        pass.set(0);
        block.set(0);
        countDown = new CountDownLatch(1);
        initDefaultFlowRule();
        simulatePulseFlow();
        countDown.await();
        System.out.println("done");
        System.out.println("total pass:" + pass.get() + ", total block:" + block.get());
        System.exit(0);
    

    private static void initPaceFlowRule() 
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        rule1.setCount(count);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        /*
         * CONTROL_BEHAVIOR_RATE_LIMITER means requests more than threshold will be queueing in the queue,
         * until the queueing time is more than @link FlowRule#maxQueueingTimeMs, the requests will be rejected.
         */
        rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
        rule1.setMaxQueueingTimeMs(20 * 1000);

        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    

    private static void initDefaultFlowRule() 
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        rule1.setCount(count);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        // CONTROL_BEHAVIOR_DEFAULT means requests more than threshold will be rejected immediately.
        rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);

        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    

    private static void simulatePulseFlow() 
        for (int i = 0; i < requestQps; i++) 
            Thread thread = new Thread(new Runnable() 
                @Override
                public void run() 
                    long startTime = TimeUtil.currentTimeMillis();
                    Entry entry = null;
                    try 
                        entry = SphU.entry(KEY);
                     catch (BlockException e1) 
                        block.incrementAndGet();
                     catch (Exception e2) 
                        // biz exception
                     finally 
                        if (entry != null) 
                            entry.exit();
                            pass.incrementAndGet();
                            long cost = TimeUtil.currentTimeMillis() - startTime;
                            System.out.println(
                                    TimeUtil.currentTimeMillis() + " one request pass, cost " + cost + " ms");
                        
                    

                    try 
                        TimeUnit.MILLISECONDS.sleep(5);
                     catch (InterruptedException e1) 
                        // ignore
                    

                    if (done.incrementAndGet() >= requestQps) 
                        countDown.countDown();
                    
                
            , "Thread " + i);
            thread.start();
        
    


创建SystemGuardDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class SystemGuardDemo 

    private static AtomicInteger pass = new AtomicInteger();
    private static AtomicInteger block = new AtomicInteger();
    private static AtomicInteger total = new AtomicInteger();

    private static volatile boolean stop = false;
    private static final int threadCount = 100;

    private static int seconds = 60 + 40;

    public static void main(String[] args) throws Exception 

        tick();
        initSystemRule();

        for (int i = 0; i < threadCount; i++) 
            Thread entryThread = new Thread(new Runnable() 
                @Override
                public void run() 
                    while (true) 
                        Entry entry = null;
                        try 
                            entry = SphU.entry("methodA", EntryType.IN);
                            pass.incrementAndGet();
                            try 
                                TimeUnit.MILLISECONDS.sleep(20);
                             catch (InterruptedException e) 
                                // ignore
                            
                         catch (BlockException e1) 
                            block.incrementAndGet();
                            try 
                                TimeUnit.MILLISECONDS.sleep(20);
                             catch (InterruptedException e) 
                                // ignore
                            
                         catch (Exception e2) 
                            // biz exception
                         finally 
                            total.incrementAndGet();
                            if (entry != null) 
                                entry.exit();
                            
                        
                    
                

            );
            entryThread.setName("working-thread");
            entryThread.start();
        
    

    private static void initSystemRule() 
        List<SystemRule> rules = new ArrayList<SystemRule>();
        SystemRule rule = new SystemRule();
        // max load is 3
        rule.setHighestSystemLoad(3.0);
        // max cpu usage is 60%
        rule.setHighestCpuUsage(0.6);
        // max avg rt of all request is 10 ms
        rule.setAvgRt(10);
        // max total qps is 20
        rule.setQps(20);
        // max parallel working thread is 10
        rule.setMaxThread(10);

        rules.add(rule);
        SystemRuleManager.loadRules(Collections.singletonList(rule));
    

    private static void tick() 
        Thread timer = new Thread(new TimerTask());
        timer.setName("sentinel-timer-task");
        timer.start();
    

    static class TimerTask implements Runnable 
        @Override
        public void run() 
            System.out.println("begin to statistic!!!");
            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;
            while (!stop) 
                try 
                    TimeUnit.SECONDS.sleep(1);
                 catch (InterruptedException e) 
                
                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;

                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;

                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;

                System.out.println(seconds + ", " + TimeUtil.currentTimeMillis() + ", total:"
                    + oneSecondTotal + ", pass:"
                    + oneSecondPass + ", block:" + oneSecondBlock);
                if (seconds-- <= 0) 
                    stop = true;
                
            
            System.exit(0);
        
    

创建WarmUpFlowDemo

代码如下(示例):

package com.example.springcloudalibabasentineldemo.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.util.TimeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class WarmUpFlowDemo 
    private static final String KEY = "abc";

    private static AtomicInteger pass = new AtomicInteger();
    private static AtomicInteger block = new AtomicInteger();
    private static AtomicInteger total = new AtomicInteger();

    private static volatile boolean stop = false;

    private static final int threadCount = 100;
    private static int seconds = 60 + 40;

    public static void main(String[] args) throws Exception 
        initFlowRule();
        // trigger Sentinel internal init
        Entry entry = null;
        try 
            entry = SphU.entry(KEY);
         catch (Exception e) 
         finally 
            if (entry != null) 
                entry.exit();
            
        

        Thread timer = new Thread(new TimerTask());
        timer.setName("sentinel-timer-task");
        timer.start();

        //first make the system run on a very low condition
        for (int i = 0; i < 3; i++) 
            Thread t = new Thread(new WarmUpTask());
            t.setName("sentinel-warmup-task");
            t.start();
        
        Thread.sleep(20000);

        /*
         * Start more thread to simulate more qps. Since we use @link RuleConstant.CONTROL_BEHAVIOR_WARM_UP as
         * @link FlowRule#controlBehavior, real passed qps will increase to @link FlowRule#count in
         * @link FlowRule#warmUpPeriodSec seconds.
         */
        for (int i = 0; i < threadCount; i++) 
            Thread t = new Thread(new RunTask());
            t.setName("sentinel-run-task");
            t.start();
        
    

    private static void initFlowRule() 
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        rule1.setCount(20);
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
        rule1.setWarmUpPeriodSec(10);

        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    

    static class WarmUpTask implements Runnable 
        @Override
        public void run() 
            while (!stop) 
                Entry entry = null;
                try 
                    entry = SphU.entry(KEY);
                    // token acquired, means pass
                    pass.addAndGet(1);
                 catch (BlockException e1) 
                    block.incrementAndGet();
                 catch (Exception e2) 
                    // biz exception
                 finally 
                    total.incrementAndGet();
                    if (entry != null) 
                        entry.exit();
                    
                
                Random random2 = new Random();
                try 
                    TimeUnit.MILLISECONDS.sleep(random2.nextInt(2000));
                 catch (InterruptedException e) 
                    // ignore
                
            
        
    

    static class RunTask implements Runnable 
        @Override
        public void run() 
            while (!stop) 
                Entry entry = null;
                try 
                    entry = SphU.entry(KEY);
                    pass.addAndGet(1);
                 catch (BlockException e1) 
                    block.incrementAndGet();
                 catch (Exception e2) 
                    // biz exception
                 finally 
                    total.incrementAndGet();
                    if (entry != null) 
                        entry.exit();
                    
                
                Random random2 = new Random();
                try 
                    TimeUnit.MILLISECONDS.sleep(random2.nextInt(50));
                 catch (InterruptedException e) 
                    // ignore
                
            
        
    

    static class TimerTask implements Runnable 

        @Override
        public void run() 
            long start = System.currentTimeMillis();
            System.out.println("begin to statistic!!!");
            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;
            while (!stop) 
                try 
                    TimeUnit.SECONDS.sleep(1);
                 catch (InterruptedException e) 
                

                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;

                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;

                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;

                System.out.println(TimeUtil.currentTimeMillis() + ", total:" + oneSecondTotal
                        + ", pass:" + oneSecondPass
                        + ", block:" + oneSecondBlock);
                if (seconds-- <= 0) 
                    stop = true;
                
            

            long cost = System.currentTimeMillis() - start;
            System.out.println("time cost: " + cost + " ms");
            System.out.println("total:" + total.get() + ", pass:" + pass.get()
                    + ", block:" + block.get());
            System.exit(0);
        
    


创建UserEntity

代码如下(示例):

package com.example.springcloudalibabasentineldemo.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * @className: RedisController
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@Data
@TableName("t_user")
public class UserEntity implements Serializable 
	private static final long serialVersionUID = 1L;

	/**
	 * 
	 */
	@TableId
	private Integer id;
	/**
	 * 
	 */
	private String username;
	/**
	 * 
	 */
	private Integer age;



创建RRException

代码如下(示例):

/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */

package com.example.springcloudalibabasentineldemo.exception;


/**
 * @description:自定义异常
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class RRException extends RuntimeException 
	private static final long serialVersionUID = 1L;
	
    private String msg;
    private int code = 500;
    
    public RRException(String msg) 
		super(msg);
		this.msg = msg;
	
	
	public RRException(String msg, Throwable e) 
		super(msg, e);
		this.msg = msg;
	
	
	public RRException(String msg, int code) 
		super(msg);
		this.msg = msg;
		this.code = code;
	
	
	public RRException(String msg, int code, Throwable e) 
		super(msg, e);
		this.msg = msg;
		this.code = code;
	

	public String getMsg() 
		return msg;
	

	public void setMsg(String msg) 
		this.msg = msg;
	

	public int getCode() 
		return code;
	

	public void setCode(int code) 
		this.code = code;
	
	
	


创建OrderFeignService

代码如下(示例):

package com.example.springcloudalibabasentineldemo.feign;

import com.example.springcloudalibabasentineldemo.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@FeignClient(value = "open-feign",path = "/feign")
public interface OrderFeignService 

    @RequestMapping("/getNacosConfigure")
    public String getNacosConfigure();


创建CommonBlockHandler

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.springcloudalibabasentineldemo.utils.R;
import java.util.Map;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class CommonBlockHandler 

    /**
     * 注意: 必须为 static 函数   多个方法之间方法名不能一样
     * @param exception
     * @return
     */
    public static R handleException(Map<String, Object> params, BlockException exception)
        return R.error(-1,"===被限流啦==="+exception);
    

    public String getNacosConfigure() 
        return "===被限流啦===";
    
    public static R handleException2(Integer id, BlockException exception)
        return R.error(-1,"===被限流啦==="+exception);
    

    public static String handleException3(BlockException exception)
        return "===被限流啦==="+exception;
    


创建CommonFallback

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;


import com.example.springcloudalibabasentineldemo.utils.R;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class CommonFallback 
    /**
     * 注意: 必须为 static 函数
     * @param e
     * @return
     */
    public static R fallback(Integer id, Throwable e)
        return R.error(-2,"===被异常降级啦==="+e.getMessage());
    

    public String getNacosConfigure() 
        return "===被异常降级啦===";
    


创建MyBlockExceptionHandler

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.example.springcloudalibabasentineldemo.utils.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@Slf4j
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler 
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception 
        log.info("BlockExceptionHandler BlockException================"+e.getRule());
        R r = null;

        if (e instanceof FlowException) 
            r = R.error(100,"接口限流了");

         else if (e instanceof DegradeException) 
            r = R.error(101,"服务降级了");

         else if (e instanceof ParamFlowException) 
            r = R.error(102,"热点参数限流了");

         else if (e instanceof SystemBlockException) 
            r = R.error(103,"触发系统保护规则了");

         else if (e instanceof AuthorityException) 
            r = R.error(104,"授权规则不通过");
        

        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(), r);

    


创建MyRequestOriginParser

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import javax.servlet.http.HttpServletRequest;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
//@Component
public class MyRequestOriginParser implements RequestOriginParser 
    /**
     * 通过request获取来源标识,交给授权规则进行匹配
     * @param request
     * @return
     */
    @Override
    public String parseOrigin(HttpServletRequest request) 
        // 标识字段名称可以自定义
        String origin = request.getParameter("serviceName");
//        if (StringUtil.isBlank(origin))
//            throw new IllegalArgumentException("serviceName参数未指定");
//        
        return origin;
    


创建MyUrlBlockHandler

代码如下(示例):

package com.example.springcloudalibabasentineldemo.sentinel;

import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.example.springcloudalibabasentineldemo.utils.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@Slf4j
public class MyUrlBlockHandler implements UrlBlockHandler 
    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException 
        log.info("UrlBlockHandler BlockException================"+e.getRule());
        R r = null;

        if (e instanceof FlowException) 
            r = R.error(100,"接口限流了");

         else if (e instanceof DegradeException) 
            r = R.error(101,"服务降级了");

         else if (e instanceof ParamFlowException) 
            r = R.error(102,"热点参数限流了");

         else if (e instanceof SystemBlockException) 
            r = R.error(103,"触发系统保护规则了");

         else if (e instanceof AuthorityException) 
            r = R.error(104,"授权规则不通过");
        

        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(), r);
    


创建UserServiceImpl

代码如下(示例):

package com.example.springcloudalibabasentineldemo.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springcloudalibabasentineldemo.dao.UserDao;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.service.UserService;
import com.example.springcloudalibabasentineldemo.utils.PageUtils;
import com.example.springcloudalibabasentineldemo.utils.Query;
import org.springframework.stereotype.Service;
import java.util.Map;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService 

    @Override
    public PageUtils queryPage(Map<String, Object> params) 
        IPage<UserEntity> page = this.page(
                new Query<UserEntity>().getPage(params),
                new QueryWrapper<UserEntity>()
        );

        return new PageUtils(page);
    

    @Override
    @SentinelResource(value = "getUser")  //aop
    public UserEntity getUser(int id)
        UserEntity user = baseMapper.selectById(id);
        return user;
    
    
    public UserEntity handleException(int id, BlockException ex) 
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername("===被限流降级啦===");
        return userEntity;
    


创建UserService

代码如下(示例):

package com.example.springcloudalibabasentineldemo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.springcloudalibabasentineldemo.entity.UserEntity;
import com.example.springcloudalibabasentineldemo.utils.PageUtils;
import java.util.Map;

/**
 * @description:
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public interface UserService extends IService<UserEntity> 

    PageUtils queryPage(Map<String, Object> params);

    UserEntity getUser(int id);



创建Constant

代码如下(示例):

/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */

package com.example.springcloudalibabasentineldemo.utils;


/**
 * @description:常量
 * @author: zhiweiLiao
 * @date: 2022-09-13 15:28
 */
public class Constant 
	/** 超级管理员ID */
	public static final int SUPER_ADMIN = 1;
    /**
     * 当前页码
     */
    public static final String PAGE = "page";
    /**
     * 每页显示记录数
     */
    public static final String LIMIT = "limit";
    /**
     * 排序字段
     */
    public static final String ORDER_FIELD = "sidx";
    /**
     * 排序方式
     */
    public static final String ORDER = "order";

以上是关于Spring Cloud Alibaba Sentinel集成的主要内容,如果未能解决你的问题,请参考以下文章