SpringCloudAlibaba项目之Sentinel流量控制

SpringCloudAlibaba随笔目录

一、SpringCloudAlibaba项目之父工程搭建

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

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

四、SpringCloud Alibaba项目之Ribbon负载均衡

五、SpringCloud Alibaba项目之 OpenFeign远程调用

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

七、SpringCloud Alibaba项目之Sentinel流量控制

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

九、SpringCloudAlibaba项目之GateWay网关

十、SpringCloudAlibaba项目之SkyWalking链路 追 踪

SpringCloudAlibaba项目之Sentinel流量控制

1、Sentinel简介

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

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

Sentinel主要特性:

SpringCloudAlibaba项目之Sentinel流量控制

2、Sentinel与Hystrix的区别

SpringCloudAlibaba项目之Sentinel流量控制

关于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

SpringCloudAlibaba项目之Sentinel流量控制

pom.xml中添加依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-coreartifactId>
    <version>1.8.2version>
dependency>
SentinelController接口:
/**
 * Sentinel接口流控测试
 */
@RestController
public class SentinelController {
    public static final String RESOURCE_NAME = "sentinel";//资源名

    //进行Sentinel流控
    @RequestMapping(value = "/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 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秒钟之内访问一次正常,如果超过一次将被流控

SpringCloudAlibaba项目之Sentinel流量控制

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

pom.xml文件添加依赖

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-annotation-aspectjartifactId>
    <version>1.8.2version>
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 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 处理逻辑。若未配置 blockHandlerfallbackdefaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。

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

SpringCloudAlibaba项目之Sentinel流量控制

SpringCloudAlibaba项目之Sentinel流量控制

5、服务降级规则体验

/**
 * Sentinel接口流控测试
 */
@RestController
public class SentinelController {
    public static final String DEGRADE_RESOURCE_NAME = "degrade";//降级资源名
/**
     * 定义服务降级规则
     *
     * spring的初始化方法
     */
    @PostConstruct
    private static void initDegradeRules(){
        //降级规则
        List 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

SpringCloudAlibaba项目之Sentinel流量控制

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&#x3002;

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

注:若您的应用为 Spring Boot 或 Spring Cloud 应用,您可以通过 Spring 配置文件来指定配置,详情请参考 Spring Cloud Alibaba Sentinel 文档

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

SpringCloudAlibaba项目之Sentinel流量控制

pom.xml文件添加依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
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 "订单服务-订单新增成功";
    }
}

整合效果:

SpringCloudAlibaba项目之Sentinel流量控制

8、BlockException统一异常处理

SpringCloudAlibaba项目之Sentinel流量控制

MyBlockExceptionHandler异常处理类:

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

/**
 * BlockException统一异常处理
 */
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        System.out.println("资源规则的详细信息:" + e.getRule());
        JSONObject resultObj = new JSONObject();
        if(e instanceof FlowException){
            resultObj.put("code",100);
            resultObj.put("msg","接口限流");
        }if(e instanceof DegradeException){
            resultObj.put("code",101);
            resultObj.put("msg","服务降级");
        }if(e instanceof ParamFlowException){
            resultObj.put("code",102);
            resultObj.put("msg","热点参数限流");
        }if(e instanceof SystemBlockException){
            resultObj.put("code",103);
            resultObj.put("msg","触发系统保护规则");
        }if(e instanceof AuthorityException){
            resultObj.put("code",104);
            resultObj.put("msg","授权规则不通过");
        }

        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("UTF-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(resultObj.toString());
    }
}

控制台添加流控规则

SpringCloudAlibaba项目之Sentinel流量控制

测试效果:

SpringCloudAlibaba项目之Sentinel流量控制

9、整合openFeign降级

SpringCloudAlibaba项目之Sentinel流量控制

pom.xml添加依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

application.properties添加配置

openfeign整合sentinel
feign.sentinel.enabled=true
StockOpenFeignServiceFallback服务降级实现类
@Component
public class StockOpenFeignServiceFallback implements StockOpenFeignService{

    @Override
    public String subStock(String id) {
        return "subStock-服务降级了!";
    }

    @Override
    public String addStock() {
        return "addStock-服务降级了!";
    }
}
StockOpenFeignService接口添加服务降级实现类
/**
 * 库存服务接口
 * name:指定调用rest接口所对应的服务名
 * path:指定调用rest接口所在的StockController指定的@RequestMapping
 */
@FeignClient(name = "service-stock",path = "stock",fallback = StockOpenFeignServiceFallback.class)
public interface StockOpenFeignService {

    //声明需要调用的rest接口对应的方法
    /**
     * 库存扣减
     * @return
     */
    @RequestMapping("/subStock/{id}")
    //@RequestLine("GET /subStock") //feign的原生注解
    String subStock(@PathVariable("id") String id);
    //String subStock(@Param("id") String id); //@PathVariable换成@Param

    /**
     * 库存新增
     * @return
     */
    @RequestMapping("/addStock")
    //@RequestLine("GET /addStock") //feign的原生注解
    String addStock();
}

访问地址:http://localhost:8082/order/addOrder

SpringCloudAlibaba项目之Sentinel流量控制

10、Sentinel规则持久化

一旦我们重启应用,Sentinel规则将消失,生产环境需要将配置规则进行持久化,将限流配置规则持久化进Nacos保存,只要刷新到某个被流控的rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对Sentinel上的流控规则持续有效。

pom.xml文件添加依赖

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-datasource-nacosartifactId>
dependency>

application.properties

spring.application.name=service-sentinel
spring.cloud.nacos.discovery.server-addr= 127.0.0.1:8848
spring.cloud.sentinel.transport.dashboard=localhost:8080
#默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
spring.cloud.sentinel.transport.port= 8719
spring.cloud.sentinel.datasource.ds1.nacos.server-addr= 127.0.0.1:8848
spring.cloud.sentinel.datasource.ds1.nacos.dataId= service-sentinel
spring.cloud.sentinel.datasource.ds1.nacos.groupId= DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.data-type= json
spring.cloud.sentinel.datasource.ds1.nacos.rule-type= flow

添加Nacos规则

SpringCloudAlibaba项目之Sentinel流量控制
[
    {
         "resource":"/order/addOrder",
         "limitApp":"default",
         "grade":1,
         "count":1,
         "strategy":0,
         "controlBehavior":0,
         "clusterMode":false
    }
]

resource: 资源名称
limitApp: 来源应用
grade: 阈值类型,0表示线程,1表示QPS
count: 单机阈值
strategy: 流控模式,0表示直接,1表示关联,2表示链路
controlBehavior: 流控效果,0表示快速失败,1表示Warm Up,2表示排队等待
clusterMode: 是否集群

Original: https://www.cnblogs.com/qiantao/p/15731471.html
Author: QianTM
Title: SpringCloudAlibaba项目之Sentinel流量控制

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/572510/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • JVM学习笔记之类加载机制【八】

    一、类加载时机 1.1 触发类初始化的六个场景: 加载? 1、遇到new、getstatic、putstatic或invokestatic这四条字节码指令时 如果类型没有进行过初始…

    Java 2023年6月5日
    073
  • 分库分表后的索引问题

    最近遇到一个慢sql,在排查过程中发现和分库分表后的索引设置有关系,总结了下问题。 在进行应用健康度盘点时,发现有个慢sql如下 select brandgoodid from b…

    Java 2023年6月8日
    0132
  • Centos下安装Maven私服Nexus

    dockers安装Nexus,指定访问路径(默认为/;在使用Nginx做反向代理时,最好指定访问路径),并在容器外持久化数据,避免Nexus容器升级后数据丢失。 安装并启动 doc…

    Java 2023年6月5日
    098
  • Assert的使用和简单解释

    Assert 的简单使用 Document d = Jsoup.connect("http://www.baidu.com").get(); Assert.no…

    Java 2023年6月15日
    068
  • MyBatis学习(一)

    MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射;MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作;MyBatis …

    Java 2023年6月6日
    065
  • Hibernate 离线对象构建通用查询

    1.业务场景 当下主系统衍生子业务系统已经成为常态,像京东的物流和金融,阿里的支付宝和淘宝。 子业务系统需要对主系统的资源进行访问,这里的资源我具体化为数据库数据,但日常业务中可能…

    Java 2023年5月29日
    065
  • [游戏引擎中文版]CatSystem2最新中文支持版

    最近有的论坛希望能自己开发GAL 而不是一味 汉化GAL 就想找程序猿帮忙。 借此机会 我推出游戏引擎中文支持版,希望大家能开发属于自己的GALGAME! 上次就为大家介绍一个引擎…

    Java 2023年5月29日
    070
  • 关于Maven的 install 和 打包

    关于安装 进入pom.xml文件目录下,使用命令mvn install 当然也可以使用类似idea这类本身已经集成好maven插件按钮的编辑器进行安装 安装过程会输出安装jar包的…

    Java 2023年6月14日
    085
  • springboot异常处理之404

    ps: 推荐一下本人的通用后台管理项目crowd-admin 以及newbee-mall 增强版,喜欢的话给个star就好 开始这篇博文的时候我们先回顾下 spring异常处理的几…

    Java 2023年6月14日
    070
  • nginx重新整理——————http请求的11个阶段中的find_config[十三]

    前言 简单介绍一下find_config 与 preaccess 阶段。 正文 find_config 很大一部分工作是进行location的匹配。 来一张图看下location指…

    Java 2023年5月30日
    070
  • 使用alembic为SQLAlchemy迁移数据

    用惯了django的迁移命令后, 发现SQLAlchemy默认没有对应的迁移命令, 但是SQLAlchemy作者为SQLAlchemy开发了迁移工具: Alembic, 其官方文档…

    Java 2023年6月7日
    072
  • Java并发工具类-CounDownLatch

    背景 * Java1.5&#x5F15;&#x5165;&#xFF0C;&#x968F;&#x4E4B;&#x4E00;&#…

    Java 2023年6月5日
    071
  • 面向对象—多态

    package com.gao.test.Test6; public class Girl { //跟猫玩 // public void play(Cat cat){ // cat…

    Java 2023年6月5日
    050
  • JavaWeb-Tomcat安全域

    安全域是 Web服务器用来保护 Web资源的一种机制. 在安全域中可以配置安全验证信息,即用户信息(包括用户名和口令),以及用户和角色的映射关系. 每个用户可以有一个或多个角色,每…

    Java 2023年5月29日
    055
  • validform学习

    1 说明 validform非常实用,可以用来进行表单验证,是基于jquery框架的,一共就导出两个文件,一个css文件,一个js文件。启动也只需一句js语句即可,相当方便。 可以…

    Java 2023年6月7日
    046
  • Java中的异常

    Java异常的体系结构 根类Throwable,其子类Error和Excepion Excepion分为运行时异常RuntimeException(也叫非检查型异常),和编译时Ex…

    Java 2023年6月15日
    066
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球