拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 SpringCloudAlibaba项目之Sentinel流量控制

SpringCloudAlibaba项目之Sentinel流量控制

白鹭 - 2022-02-22 2125 0 0

SpringCloudAlibaba随笔目录

一、SpringCloudAlibaba项目之父工程搭建

二、SpringCloudAlibaba项目之Nacos搭建及服务注册

三、SpringCloudAlibaba项目之生产者与消费者

四、SpringCloudAlibaba项目之Ribbon负载均衡

五、SpringCloudAlibaba项目之OpenFeign远程呼叫

六、SpringCloudAlibaba项目之Nacos-config配置中心

七、SpringCloudAlibaba项目之Sentinel流量控制

八、SpringCloudAlibaba项目之Seata分布式事务

九、SpringCloudAlibaba项目之GateWay网关

十、SpringCloudAlibaba项目之SkyWalking链路跟踪

 

SpringCloudAlibaba项目之Sentinel流量控制

1、Sentinel简介

  Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性,

官网:https://github.com/alibaba/Sentinel/wiki

Sentinel主要特性:

 2、Sentinel与Hystrix的区别

  

关于Sentinel与Hystrix的区别见:https://yq.aliyun.com/articles/633786/

总体来说:

  Hystrix常用的执行绪池隔离会造成执行绪上下切换的overhead比较大;Hystrix使用的信号量隔离对某个资源呼叫的并发数进行控制,效果不错,但是无法对慢呼叫进行自动降级;Sentinel通过并发执行绪数的流量控制提供信号量隔离的功能;

此外,Sentinel支持的熔断降级维度更多,可对多种指标进行流控、熔断,且提供了实时监控和控制面板,功能更为强大,

  Sentinel 的所有规则都可以在存储器态中动态地查询及修改,修改之后立即生效,同时 Sentinel 也提供相关 API,供您来定制自己的规则策略,

Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则 和 热点自变量规则,

3、使用Sentinel 核心库体验流量控制

  我们先使用springboot应用程序,快速搭建使用,体验流控效果,

 官网:https://github.com/alibaba/Sentinel/wiki/%E6%96%B0%E6%89%8B%E6%8C%87%E5%8D%97#%E5%85%AC%E7%BD%91-demo

 pom.xml中添加依赖

<!-- springweb 启动依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- sentinel 核心库 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.2</version>
</dependency>
SentinelController界面:
/**
 * Sentinel界面流控测验
 */
@RestController
public class SentinelController {
    public static final String RESOURCE_NAME = "sentinel";//资源名

    //进行Sentinel流控
    @RequestMapping(value = "https://www.cnblogs.com/sentinel")
    public String sentinelTest(){
        Entry entry = null;
        try {
            //sentinel针对资源进行限制
            entry = SphU.entry(RESOURCE_NAME);
            //被保护的业务逻辑
            String str = "Sentinel界面正常";
            System.out.println("====" + str + "====");
            return str;
        } catch (BlockException e) {
            e.printStackTrace();
            //资源访问阻止,被限流或被降级
            //进行相应的处理操作
            System.out.println("Sentinel界面被流控了");
            return "Sentinel界面被流控了";
        }catch (Exception e){
            // 若需要配置降级规则,需要通过这种方式记录业务例外
            Tracer.traceEntry(e,entry);
        }finally {
            if(entry != null){
                entry.exit();
            }
        }
        return null;
    }

    /**
     * 定义规则
     *
     * spring的初始化方法
     */
    @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);
    }
}

访问地址:http://localhost:8080/sentinel

1秒钟之内访问一次正常,如果超过一次将被流控

 4、@SentinelResource 注解方式定义资源

 pom.xml档案添加依赖

<!-- 使用 @SentinelResource 注解依赖 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.2</version>
</dependency>

 SentinelAspectConfiguration配置bean

/**
 * 若您的应用使用了 Spring AOP(无论是 Spring Boot 还是传统 Spring 应用),
 * 您需要通过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean:
 */
@Configuration
public class SentinelAspectConfiguration {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}
SentinelController:
/**
 * Sentinel界面流控测验
 */
@RestController
public class SentinelController {
    public static final String USER_RESOURCE_NAME = "user";//资源名
/**
     * 定义规则
     *
     * spring的初始化方法
     */
    @PostConstruct
    private static void initFlowRules(){
        //流控规则
        List<FlowRule> rules = new ArrayList<>();//流控
        FlowRule rule2 = new FlowRule();
        //设定受保护的资源
        rule2.setResource(USER_RESOURCE_NAME);
        // 设定流控规则 QPS
        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //设定受保护资源的阈值
        // Set limit QPS to 20.
        rule2.setCount(1);
        rules.add(rule2);

        //加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }

    /**
     * 使用@SentinelResource进行Sentinel流控
     * @SentinelResource注解改善界面钟资源定义和被流控降级后的处理方法
     * 使用方法:1、添加依赖
     *           2、配置bean-SentinelResourceAspect
     *  value:定义流控资源
     *  blockHandler:设定流控降级后的处理方法(默认该方法必须宣告在同一个类)
     *      如果不想在同一个类中,可以使用 blockHandlerClass 指定,但是方法必须是static
     *  fallback:当界面出现例外,就可以交给fallback指定的方法进行处理
     *      如果不想在同一个类中,可以使用 fallbackClass 指定,但是方法必须是static
     *
     *  注意:如果blockHandler和fallback方法同时指定了,则blockHandler优先级更高
     * @param id
     * @return
     */
    @RequestMapping(value = "/user")
    @SentinelResource(value = USER_RESOURCE_NAME,blockHandler = "blockHandlerForUserTest",fallback = "fallbackForUserTest")
    public User userTest(String id){
        int a = 1/0;
        return new User("张三");
    }

    /**
     * userTest流控降级后的处理方法
     * 注意:
     * 1、一定要是public
     * 2、回传值一定要和源方法(userTest)保证一致,包含源方法的自变量
     * 3、可以在自变量最后添加BlockException,可以区分是什么规则的处理方法
     * @param id
     * @param ex
     * @return
     */
    public User blockHandlerForUserTest(String id,BlockException ex){
        ex.printStackTrace();
        return new User("流控!");
    }

    /**
     * userTest例外后的处理方法
     * 注意:
     * 1、一定要是public
     * 2、回传值一定要和源方法(userTest)保证一致,包含源方法的自变量
     * 3、可以在自变量最后添加Throwable,可以区分是什么例外
     * @param id
     * @param e
     * @return
     */
    public User fallbackForUserTest(String id,Throwable e){
        e.printStackTrace();
        return new User("例外处理!");
    }
}

特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑,若未配置 blockHandlerfallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException),

访问地址:http://localhost:8080/user

 5、服务降级规则体验

/**
 * Sentinel界面流控测验
 */
@RestController
public class SentinelController {
    public static final String DEGRADE_RESOURCE_NAME = "degrade";//降级资源名
/**
     * 定义服务降级规则
     *
     * spring的初始化方法
     */
    @PostConstruct
    private static void initDegradeRules(){
        //降级规则
        List<DegradeRule> DegradeRules = new ArrayList<>();
        //流控
        DegradeRule degradeRule = new DegradeRule();
        //设定受保护的资源
        degradeRule.setResource(DEGRADE_RESOURCE_NAME);
        // 设定规则测率: 例外数
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        //设定例外数
        degradeRule.setCount(2);
        degradeRule.setTimeWindow(10);//10秒内发生的例外
        degradeRule.setMinRequestAmount(2);//最小请求数

        DegradeRules.add(degradeRule);
        //加载配置好的规则
        DegradeRuleManager.loadRules(DegradeRules);
    }

    @RequestMapping("/degrade")
    @SentinelResource(value = DEGRADE_RESOURCE_NAME,entryType = EntryType.IN,blockHandler = "blockHandlerForDegrade")
    public User degrade(String id) throws InternalException {
        // 例外数/比例
        throw new RuntimeException("例外");

        //慢呼叫比例
        /*TimeUnit.SECONDS.sleep(1);
        return new User("正常");*/
    }
/**
     * degrade服务降级的处理方法
     *
     * @param id
     * @param ex
     * @return
     */
    public User blockHandlerForDegrade(String id,BlockException ex){
        ex.printStackTrace();
        return new User("降级处理!");
    }
}

访问地址:http://localhost:8080/degrade

 6、控制台部署

控制台档案:https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0

github下载地址(下载对应版本):https://github.com/alibaba/Sentinel/releases

组件版本关系:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

从 release 页面 下载最新版本的控制台 jar 包,使用如下命令启动控制台:

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

其中 -Dserver.port=8080 用于指定 Sentinel 控制台埠为 8080,

从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel,可以参考 鉴权模块档案 配置用户名和密码,

7、客户端接入控制台(整合SpringCloud Alibaba)

 

 pom.xml档案添加依赖

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

application.properties

# 应用名称
spring.application.name=service-sentinel
# 应用服务 WEB 访问埠
server.port=8081
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8858
# 取消Sentinel控制台懒加载
# 默认情况下 Sentinel 会在客户端首次呼叫的时候进行初始化,开始向控制台发送心跳包
# 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
spring.cloud.sentinel.eager=true
# 如果有多套网络,又无法正确获取本机IP,则需要使用下面的自变量设定当前机器可被外部访问的IP地址,供admin控制台使用
# spring.cloud.sentinel.transport.client-ip=
OrderController
/**
 * 订单服务
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    /**
     * 新增订单
     * @return
     */
    @RequestMapping("/addOrder")
    public String addOrder(){
        System.out.println("订单新增成功");

        return "订单服务-订单新增成功";
    }
}

整合效果:

 8、BlockException统一例外处理

 

 MyBlockExceptionHandler例外处理类:

注意:想使用BlockException统一例外处理时,不能添加@SentinelResource

/**
 * BlockException统一例外处理
 */
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public
							
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *