• Sentinel基础学习


    Sentinel限流控制

    1. 通过硬编码方式进行限流控制
        // 定义限流规则
        @PostConstruct
        public void initFlowRules() {
            // 创建存放限流规则的集合
            List<FlowRule> rules = new ArrayList<>();
            // 创建限流规则
            FlowRule rule = new FlowRule();
            // 定义资源,标识Sentinel会对哪个资源生效
            rule.setResource("HelloResource1");
            // 定义限流规则类型 QPS限流类型
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            // 定义QPS每秒能通过的请求个数
            rule.setCount(2.0);
            // 将限流规则存放到集合中
            rules.add(rule);
            // 加载限流规则
            FlowRuleManager.loadRules(rules);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    1. 通过Sentinel 控制台的方式来进行限流控制:https://sentinelguard.io/zh-cn/docs/dashboard.html

    Sentinel资源定义

    1. 抛出异常的方式定义资源
        /**
         * 抛出异常的方式定义资源
         * Sentinel中的SphU包含了try-catch风格的API。用这种方式,当资源翻身了限流之后会抛出BlockException。这个时候可以捕获异常,进行限流之后的逻辑处理。
         */
        @GetMapping("/hello1")
        public String hello1() {
            // 限流入口
            // 使用限流规则监控保护资源
            try (Entry entry = SphU.entry("HelloResource1")) {
                LocalDateTime now = LocalDateTime.now();
                // 被保护的资源
                return "Hello, Now is " + dateTimeFormatter.format(now);
            } catch (BlockException exception) {
                exception.printStackTrace();
                log.error("Exception is : {}", exception);
                // 被限流或是被降级的操作处理
                return "系统繁忙,请稍候重试";
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 返回布尔值方式定义资源
        /**
         * 返回Boolean值方式定义资源
         * Sentinel中的SphO提供if-else风格的API。用这种方式,当资源发生了限流之后会返回false,这个时候可以根据返回值,进行限流之后的逻辑处理
         * SphO.entry()需要与SphO.exit()方法成对出现,否则会导致调用链记录异常,抛出ErrorEntryFreeException
         */
        @GetMapping("/hello2")
        public String hello2() {
            // 进行限流控制,限流入口
            if (SphO.entry("HelloResource2")) {
                try {
                    // 被保护的资源
                    log.info("访问成功");
                    return "Hello, Now is " + dateTimeFormatter.format(LocalDateTime.now());
                } finally {
                    // 限流出口
                    SphO.exit();
                }
            } else {
                // 被限制或者降级的处理
                log.info("系统繁忙,请稍候重试");
                return "系统繁忙,请稍候重试";
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    1. 异步调用支持

    先定义异步Service,并开启异步

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.concurrent.TimeUnit;
    
    @Service
    @Slf4j
    public class HelloService {
        private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
        @Async
        public void hello3() {
            log.info("异步开始: {}", dateTimeFormatter.format(LocalDateTime.now()));
            try {
                TimeUnit.SECONDS.sleep(2L);
            } catch (InterruptedException exception) {
                log.error("exception is {}", exception);
            }
            log.info("异步结束: {}", dateTimeFormatter.format(LocalDateTime.now()));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
        /**
         * 异步调用支持
         * Sentinel支持异步调用链路的统计。在异步调用中,需要通过SphU.asyncEntry()方法定义资源,并通常需要在异步的回调函数中调用exit方法
         */
        @GetMapping("/hello3")
        public String hello3() {
            // 进行限流控制
            AsyncEntry asyncEntry = null;
            try {
                // 限流入口
                asyncEntry = SphU.asyncEntry("HelloResource3");
                // 异步方法调用
                helloService.hello3();
                return "Hello, Now is " + dateTimeFormatter.format(LocalDateTime.now());
            } catch (BlockException exception) {
                // 被限流或者降级的处理
                return "系统繁忙,请稍候重试";
            } finally {
                if (Objects.nonNull(asyncEntry)) {
                    // 限流出口
                    asyncEntry.exit();
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 注解方式定义资源

    需要引入

    		<dependency>
    			<groupId>com.alibaba.cspgroupId>
    			<artifactId>sentinel-annotation-aspectjartifactId>
    			<version>1.7.2version>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置SentinelResourceAspect

    import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class SentinelAspectJConfiguration {
    
        @Bean
        public SentinelResourceAspect sentinelResourceAspect() {
            return new SentinelResourceAspect();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
        /**
         * 注解方式定义资源
         * Sentinel支持通过@SentinelResource注解定义资源并配置blockHandler函数来进行限流之后的处理
         */
        @GetMapping("/hello4")
        // 定义限流资源和限流降级回调函数
        @SentinelResource(value = "HelloResource4", blockHandler = "exceptionHandler")
        public String hello4() {
            return "Hello, Now is " + dateTimeFormatter.format(LocalDateTime.now());
        }
    
        // blockHandler函数,原方法调用被限流/降级/系统保护时候被调用,不能为private
        public String exceptionHandler(BlockException exception) {
            log.error("exception is {}", exception);
            return "系统繁忙,请稍候重试";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    完整pom.xml文件:

    
    <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.0modelVersion>
    	<parent>
    		<groupId>org.springframework.bootgroupId>
    		<artifactId>spring-boot-starter-parentartifactId>
    		<version>2.4.2version>
    		<relativePath/> 
    	parent>
    	<groupId>com.lwy.itgroupId>
    	<artifactId>sentinel-demoartifactId>
    	<version>0.0.1-SNAPSHOTversion>
    	<name>sentinel-demoname>
    	<description>Demo project for Spring Boot Sentineldescription>
    	<properties>
    		<java.version>1.8java.version>
    	properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-webartifactId>
    		dependency>
    
    		<dependency>
    			<groupId>com.alibaba.cspgroupId>
    			<artifactId>sentinel-coreartifactId>
    			<version>1.8.5version>
    		dependency>
    
    		<dependency>
    			<groupId>com.alibaba.cspgroupId>
    			<artifactId>sentinel-transport-simple-httpartifactId>
    			<version>1.8.5version>
    		dependency>
    
    		<dependency>
    			<groupId>com.alibaba.cspgroupId>
    			<artifactId>sentinel-annotation-aspectjartifactId>
    			<version>1.8.5version>
    		dependency>
    
    		<dependency>
    			<groupId>org.projectlombokgroupId>
    			<artifactId>lombokartifactId>
    			<optional>trueoptional>
    		dependency>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-testartifactId>
    			<scope>testscope>
    		dependency>
    	dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.bootgroupId>
    				<artifactId>spring-boot-maven-pluginartifactId>
    				<configuration>
    					<excludes>
    						<exclude>
    							<groupId>org.projectlombokgroupId>
    							<artifactId>lombokartifactId>
    						exclude>
    					excludes>
    				configuration>
    			plugin>
    		plugins>
    	build>
    
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    更多学习参考官方文档:https://sentinelguard.io/zh-cn/docs/quick-start.html

  • 相关阅读:
    Linux共享内存的操作
    华为云国际站账号购买:WeLink安全服务,为企业数字化转型保驾护航
    7个技巧让你写出干净的 TSX 代码
    Maven最新版的下载与安装教程(详细教程)
    数据是一种资产|如何实现数据价值最大化
    ruoyi-nbcio版本从RuoYi-Flowable-Plus迁移过程记录
    深入理解比特币原理1----常用术语与概念介绍
    单片机通过串口发送AT指令控制ESP8266连接服务器—Station模式
    (66)MIPI DSI LLP介绍(六)
    通信原理板块——利用香农公式对连续信道的信道容量计算
  • 原文地址:https://blog.csdn.net/liwenyang1992/article/details/126295260