• 【Sentinel】Sentinel配置zk持久化


    代码

    import cn.hutool.core.util.StrUtil;
    import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
    import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.TypeReference;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.zookeeper.ZookeeperProperties;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.Resource;
    import java.util.List;
    
    @Component
    public class ZkDataSourceConfig {
    
        @Value("${spring.application.name}")
        private String appname;
    
        @Value("${spring.profiles.active}")
        private String profile;
    
        @Resource
        private ZookeeperProperties zookeeperProperties;
    
        @PostConstruct
        public void init() {
            loadRules(zookeeperProperties.getConnectString());
        }
    
    
        private void loadRules(String remoteAddress) {
    
            // 规则会持久化到zk的/groupId/flowDataId节点
            // groupId和和flowDataId可以用/开头也可以不用
            // 建议不用以/开头,目的是为了如果从Zookeeper切换到Nacos的话,只需要改数据源类名就可以
            String groupId = StrUtil.format("sentinel/{}:{}", appname, profile);
            
            ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(remoteAddress, groupId, "FlowRule",
                    // source 就是从 zookeeper 中读出来的字符串
                    source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                    }));
            //限流
            FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    
            ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new ZookeeperDataSource<>(remoteAddress, groupId, "DegradeRule",
                    // source 就是从 zookeeper 中读出来的字符串
                    source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
                    }));
            //降级
            DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
        }
    }
    
    
    • 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

    ZK配置参考

    /sentinel/应用名:环境=FlowRule=[{"resource": "资源1", "limitApp": "default", "grade": 1, "count": 40.0, "strategy": 0, "controlBehavior": 2, "maxQueueingTimeMs": 100000 }, {"resource": "资源2", "limitApp": "default", "grade": 1, "count": 40.0, "strategy": 0, "controlBehavior": 2, "maxQueueingTimeMs": 100000 }, {"resource": "资源3", "limitApp": "default", "grade": 1, "count": 10.0, "strategy": 0, "controlBehavior": 2, "maxQueueingTimeMs": 100000 } ]
    
    • 1

    使用

    public class demo {
        public static void main(String[] args) {
            // 定义规则
            initFlowRules();
            //用SphU.entry()的形式定义资源
            while (true) {
                try (Entry entry = SphU.entry("myResource")) {//与规则定义中的rule.setResource("myResource")一致
                    // 被保护的业务逻辑...
                    System.out.println("业务资源访问成功!");
                } catch (BlockException ex) {
                    // 处理被流控的逻辑:限流或降级...
                    System.out.println("资源访问失败!!!");
                } finally {
                	if (entry != null) {
                		entry.exit();//必须退出资源调用
                    }
                }
            }
            
            
            //用SphO.entry()的形式定义资源
            while (true) {
                if(SphO.entry("myResource")){//与规则定义中的rule.setResource("myResource")一致
                    try{
                        // 被保护的业务逻辑...
                        System.out.println("业务资源访问成功!");
                    } catch (BlockException ex) {
                        // 处理被流控的逻辑:限流或降级...
                        System.out.println("资源访问失败!!!");
                    }finally{
                        SphO.exit();//必须退出资源调用
                    }
                }
            }
            
            //上面两种方式对代码侵入性很高,可用注解的方式定义资源
            while(true){
                getUserById("111");
            }
        }
    	
    	//文章开始通过zk加载配置,此处通过代码定义规则	
        //定义规则 
        private static void initFlowRules(){
            List<FlowRule> rules = new ArrayList<>();// 存储规则 FlowRule
            FlowRule rule = new FlowRule();
            rule.setResource("myResource");	// 指定限流规则作用于哪个资源上,资源名为字符串,可为任意有标识意义的方法名/接口名/其他字符串,此处资源名为"myResource"
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);	// 限流类型为QPS模式:限制QPS
            rule.setCount(10);	   // QPS不得超出10
            rule.setLimitApp("default");	// 针对的调用来源,default代表不区分来源
            rules.add(rule);
            FlowRuleManager.loadRules(rules);// 加载规则
    	}
    	
    	
    	//定义"myResource"资源,并设置违背sentinel流控规则时的处理方法handlerException()
    	@SentinelResource(value="myResource",blockHandler="handlerException")
    	public User getUserById(String id){
    	    return new User("数据库用户")}
    	//注意:此处理方法的参数必须和定义资源的方法getUserById参数一致()同时加上【BlockException exception】参数
    	public User handlerException(String id,BlockException exception){
    	    return new User("流控用户");
    	}
    }
    
    • 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
    Entry entry = null;
    try {
    	entry = SphU.entry("myResource"); //此处说明资源
    	// 被保护的业务逻辑
    	...
    } catch (BlockException e1) {
    	// 资源访问阻止,被限流或被降级,进行相应的处理操作
    	...
    } finally {
    	if (entry != null) {
    		entry.exit();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    现代android 动态权限,两种不同写法
    HTML期末作业 蛋糕bootstrap响应式网站html+css+javascript+jquery+bootstarp
    Thymeleaf常见属性
    【项目实战】单数据源多数据库实现多租户
    字符串,字符数组,类型转换,整数越界,浮点数,枚举
    线扫相机DALSA--分频倍频计算公式及原理
    分布式数据库理论知识之CAP理论、ACID原则及分布式事务一致性算法
    移动端APP测试-如何指定测试策略、测试标准?
    微服务调用链路追踪
    【面经】美团大数据开发面经
  • 原文地址:https://blog.csdn.net/zqskr_/article/details/139069922