Sentinel 简单使用案例

Sentinel 的简单介绍与使用

gradle 中的主要配置

ext {
    set('springCloudAlibabaVersion', "2.2.1.RELEASE")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-sentinel'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }

    //compile 'com.alibaba.csp:sentinel-core:1.4.0'
    //compile 'com.alibaba.csp:sentinel-transport-simple-http:1.4.0' 控制台
}

application.properties

server.port=8088
spring.cloud.sentinel.transport.port=8089
#spring.cloud.sentinel.filter.enabled=false

package com.study.sentineldemo.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
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.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
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.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * @Auther: jmx
 * @Date: 2020/11/17
 * @Description: DemoController 一个案例教程 官网教程https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5
 * @Version 1.0.0
 */
@RestController
@RequestMapping("/demo")
public class DemoController {
    /**
     * 基本概念的介绍
     * Sentinel :可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。主要用于流量控制,熔断降级
     * 资源:可以是任何东西,服务,服务里的方法,甚至是一段代码。
     *      使用 Sentinel 来进行资源保护,主要分为几个步骤: 定义资源,定义规则,检验规则是否生效
     *
     *
     *
     *
     *  额外说一下,这个在SentinelWebInterceptor中会给所有的Controller请求定义资源 资源的名称就是映射的地址 (/demo/defineByThrowException1) 通过
     *  spring.cloud.sentinel.filter.enabled=false 可以使其不生效
     */
    //抛出异常的方式定义资源
    //SphU.entry(xxx) 需要与 entry.exit() 方法成对出现,匹配调用,否则会导致调用链记录异常,抛出 ErrorEntryFreeException 异常。常见的错误:
    //自定义埋点只调用 SphU.entry(),没有调用 entry.exit()
    //顺序错误,比如:entry1 -> entry2 -> exit1 -> exit2,应该为 entry1 -> entry2 -> exit2 -> exit1
    @RequestMapping("/defineByThrowException1")
    public String defineByThrowException1(){
        String result = null;
        // 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
        // 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
        try (Entry entry = SphU.entry("defineByThrowException1")) {
            //doSomethingwork 被保护的业务逻辑
            result = "defineByThrowException1 ok";
        } catch (BlockException ex) {
            // 资源访问阻止,被限流或被降级
            // 在此处进行相应的处理操作
            result=ex.toString();
            ex.printStackTrace();
        }
        return result;
    }

    @RequestMapping("/defineByThrowException2")
    public String defineByThrowException2(){
        //特别地,若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),
        // 否则可能会有统计错误。这个时候不能使用 try-with-resources 的方式。另外通过 Tracer.trace(ex) 来统
        // 计异常信息时,由于 try-with-resources 语法中 catch 调用顺序的问题,会导致无法正确统计异常数,因此统
        // 计异常信息时也不能在 try-with-resources 的 catch 块中调用 Tracer.trace(ex)。

        //SphU.entry() 的参数描述:
        //参数名	    类型	                                    解释	                                                             默认值
        //entryType	EntryType	资源调用的流量类型,是入口流量(EntryType.IN)还是出口流量(EntryType.OUT),注意系统规则只对 IN 生效	EntryType.OUT
        //count	    int	        本次资源调用请求的 token 数目	                                                                    1
        //args	    Object[]	传入的参数,用于热点参数限流	                                                                        无

        String result = null;
        Entry entry = null;
        // 务必保证 finally 会被执行
        try {
            // 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名
            // EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效
            entry = SphU.entry("自定义资源名");
            // 被保护的业务逻辑
            // do something...
            result = "defineByThrowException2 ok";
        } catch (BlockException ex) {
            // 资源访问阻止,被限流或被降级
            // 进行相应的处理操作
            result=ex.toString();
            ex.printStackTrace();
        } catch (Exception ex) {
            // 若需要配置降级规则,需要通过这种方式记录业务异常
            Tracer.traceEntry(ex, entry);
            result=ex.toString();
            ex.printStackTrace();
        } finally {
            // 务必保证 exit,务必保证每个 entry 与 exit 配对
            if (entry != null) {
                entry.exit();
            }
        }


        //热点参数
//        Entry entry = null;
//        try {
//            // 若需要配置例外项,则传入的参数只支持基本类型。
//            // EntryType 代表流量类型,其中系统规则只对 IN 类型的埋点生效
//            // count 大多数情况都填 1,代表统计为一次调用。
//            entry = SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);
//            // Your logic here.
//        } catch (BlockException ex) {
//            // Handle request rejection.
//        } finally {
//            // 注意:exit 的时候也一定要带上对应的参数,否则可能会有统计错误。
//            if (entry != null) {
//                entry.exit(1, paramA, paramB);
//            }
//        }

        return result;

    }
    //返回布尔值方式定义资源
    @RequestMapping("/defineByReturnBoolean")
    public String defineByReturnBoolean(){
        //SphO 提供 if-else 风格的 API。用这种方式,当资源发生了限流之后会返回 false,这个时候可以根据返回值,进行限流之后的逻辑处理。
        //SphO.entry(xxx) 需要与 SphO.exit()方法成对出现,匹配调用,位置正确,否则会导致调用链记录异常,抛出ErrorEntryFreeException` 异常。
        String result = null;
       if (SphO.entry("defineByReturnBoolean")){
           try {
                //dosomethingwork
               //业务逻辑
               result="defineByReturnBoolean ok";
           }finally {
               SphO.exit();//必须执行
           }
       }else {
           // 资源访问阻止,被限流或被降级
           // 进行相应的处理操作

           result = "defineByReturnBoolean Not ok";
       }
        return result;
    }

    //注解方式定义资源
    //fallback :熔断处理方法(或降级方法)
    //exceptionsToIgnore:什么异常不过滤
    @RequestMapping("/defineByAnnotation")
    @SentinelResource(value = "defineByAnnotation",blockHandler = "defineByAnnotationHandler",fallback = "defineByAnnotatioFallback")
    public String defineByAnnotation(String id) {
        int i = 1/0;
        return "defineByAnnotation ok";
    }

    // blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
    public String defineByAnnotationHandler(String id,BlockException e){
//        BlockException e 必须存在不然不会执行
        e.printStackTrace();
        System.out.println("defineByAnnotationHandler not ok");
        return "defineByAnnotationHandler";
    }

    public String defineByAnnotatioFallback(String id){
        System.out.println("defineByAnnotatioFallback not ok");
        return "defineByAnnotatioFallback";
    }




    @PostConstruct
    public void init(){
        initFlowQpsRule();
        initDegradeRule();
        intitParamFlowRule();
    }
    //流量控制规则 (FlowRule)
    //流量规则的定义
    //Field             说明	                                                    默认值
    //resource	        资源名,资源名是限流规则的作用对象
    //count	            限流阈值
    //grade	            限流阈值类型,QPS 模式(1)或并发线程数模式(0)	            QPS 模式
    //limitApp	        流控针对的调用来源	                                        default,代表不区分调用来源
    //strategy	        调用关系限流策略:直接、链路、关联	                        根据资源本身(直接)
    //controlBehavior	流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流	直接拒绝
    //clusterMode	    是否集群限流	                                            否
    public void initFlowQpsRule() {
        //其实后面可以用管理控制台直接设置,所以这里可以了解一下相关的属性
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule("defineByAnnotation");
        rule.setCount(1);//用于测试
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("default");//限制所有
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }



//    熔断降级规则 (DegradeRule)
//    熔断降级规则包含下面几个重要的属性:
//
//    Field	                说明	                                                                            默认值
//    resource	            资源名,即规则的作用对象
//    grade	                熔断策略,支持慢调用比例/异常比例/异常数策略	                                        慢调用比例
//    count	                慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
//    timeWindow	        熔断时长,单位为 s
//    minRequestAmount	    熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)	            5
//    statIntervalMs	    统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)	                            1000 ms
//    slowRatioThreshold	慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

//慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。
//      当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔
//      断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则
//      会再次被熔断。(响应时间慢->熔断降级)
//异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自
//      动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异
//      常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。(单位时间异常数占单位总请求数的比例大->熔断降级)
//异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的
//      一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。(单位时间内异常数达到->熔断降级)
// 注意异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。

    public void initDegradeRule(){
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule();
        rule.setResource("defineByAnnotation");
        rule.setCount(1);//set threshold RT, 10 ms
        rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        rule.setTimeWindow(10);//熔断时长 单位秒
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);

    }


    // 系统保护规则 (SystemRule) 一般不用
    //Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,
    //      通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
    //Field	                    说明	                                                    默认值
    //highestSystemLoad	    load1 触发值,用于触发自适应控制阶段	                        -1 (不生效)
    //avgRt	                所有入口流量的平均响应时间	                                -1 (不生效)
    //maxThread	               入口流量的最大并发数	                                    -1 (不生效)
    //qps	                所有入口资源的 QPS	                                        -1 (不生效)
    //highestCpuUsage	    当前系统的 CPU 使用率(0.0-1.0)	                        -1 (不生效)

    //private void initSystemRule() {
    //    List<SystemRule> rules = new ArrayList<>();
    //    SystemRule rule = new SystemRule();
    //    rule.setHighestSystemLoad(10);
    //    rules.add(rule);
    //    SystemRuleManager.loadRules(rules);
    //}
    //注意系统规则只针对入口资源(EntryType=IN)生效。

    //访问控制规则 (AuthorityRule)
    // Sentinel 的访问控制(黑白名单)的功能。黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;
    //  若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
    //授权规则,即黑白名单规则(AuthorityRule)非常简单,主要有以下配置项:
    //resource:资源名,即规则的作用对象
    //limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
    //strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式
    //调用方信息通过 ContextUtil.enter(resourceName, origin) 方法中的 origin 参数传入。

    //希望控制对资源 test 的访问设置白名单,只有来源为 appA 和 appB 的请求才可通过,则可以配置如下白名单规则:
    //
    //AuthorityRule rule = new AuthorityRule();
    //rule.setResource("test");
    //rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
    //rule.setLimitApp("appA,appB");
    //AuthorityRuleManager.loadRules(Collections.singletonList(rule));



    //热点参数限流
    //热点即经常访问的数据,热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊
    //  的流量控制,仅对包含热点参数的资源调用生效。举个例子就是根据请求/ip请求(资源)的参数进行单独的限制,进行限制的参数范围就是热点参数范围

     paramA in index 0, paramB in index 1.
     若需要配置例外项或者使用集群维度流控,则传入的参数只支持基本类型。
    //SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);
    //注意:若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),否则可能会有统计错误

    //热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule):
    //
    //属性	                说明  	                                                         默认值
    //resource	            资源名,必填
    //count	                限流阈值,必填
    //grade	                限流模式	                                                        QPS 模式
    //durationInSec	        统计窗口时间长度(单位为秒),1.6.0 版本开始支持	                       1s
    //controlBehavior	    流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持	快速失败
    //maxQueueingTimeMs	    最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持	0ms
    //paramIdx	            热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置
    //paramFlowItemList	    参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的
    //                      限制。仅支持基本类型和字符串类型

    //clusterMode	        是否是集群参数流控规则	                                            false
    //clusterConfig	        集群流控相关配置


    public void intitParamFlowRule(){



        ParamFlowRule rule = new ParamFlowRule("paramrule")
                .setParamIdx(0)
                .setCount(5);//对下标为0的热点参数进行限流
        ParamFlowItem item = new ParamFlowItem().setObject("111").setClassType(String.class.getName()).setCount(1);
        rule.setParamFlowItemList(Collections.singletonList(item));//参数值为111 的进行限流
        ParamFlowRuleManager.loadRules(Collections.singletonList(rule));

    }

    @SentinelResource(value = "paramrule",blockHandler = "paramRuleHandler")
    @RequestMapping("/paramrule")
    public String paramrule(String rule){
        return rule;
    }

    public String paramRuleHandler(String rule ,BlockException e){
        e.printStackTrace();
        return "paramRuleHandler";
    }
}

package com.study.sentineldemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SentinelDemoApplication {

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

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值