0
点赞
收藏
分享

微信扫一扫

SpringCloud Sentinel 使用

雨鸣静声 2022-11-25 阅读 113

目录

一、前言

1、什么是Sentinel?

2、安装与启动

二、SpringBoot整合Sentinel

1、说明

2、将服务注册到Sentinel

三、功能展示

1、实时监控

2、流量控制

3、配置流控效果

4、降级规则

5、热点规则

6、系统规则

6.1、代码

6.2、效果

6.3、代码

6.4、添加流控规则

6.5、触发效果

7、熔断

四、规则持久化

1、规则丢失

2、如何做?


一、前言

1、什么是Sentinel?

Sentinel的生态圈 

Sentinel 主要特性

2、安装与启动

打开网址:https://github.com/alibaba/Sentinel/releases

找到合适的版本进行下载

下载本地后保存到任意目录(不要中文目录)然后在该目录下打开cmd使用命令打开

windows版本

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

linux版本

java -jar sentinel-dashboard-1.8.1.jar

有上图的界面就是已经启动成功了,在浏览器输入 http://localhost:8080/ (注意端口号占用问题,默认的8080与tomcat默认的端口号相同)

账号与密码都是 sentinel

看到这界面就启动成功了

二、SpringBoot整合Sentinel

1、说明

sentinel组件由2部分构成:核心库与控制台

2、将服务注册到Sentinel

pom文件要导入的依赖

<dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件+actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <!-- Spring Boot 提供了一组开发工具 spring-boot-devtools 可以提高开发者的工作效率,开发者可以将该模块包含在任何项目中,spring-boot-devtools 最方便的地方莫过于热部署了。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
​
    </dependencies>

.yaml文件

server: 
  port: 8401
​
spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        #Nacos服务注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719
​
management:
  endpoints:
    web:
      exposure:
        include: '*'

主启动类

@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401
{
    public static void main(String[] args) {
        SpringApplication.run(MainApp8401.class, args);
    }
}

业务类FlowLimitController

@RestController
public class FlowLimitController
{
    @GetMapping("/testA")
    public String testA()
    {
        return "------testA";
    }
​
    @GetMapping("/testB")
    public String testB()
    {
        return "------testB";
    }
}

启动我们的项目,访问路径 http://localhost:8401/testA,效果如下

此时服务已经注册进来了

三、功能展示

1、实时监控

同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在"实时监控"下。

2、流量控制

什么是QPS?

3、配置流控效果

具体可查看下图

4、降级规则

降级规则就是设置当满足什么条件的时候,对服务进行降级。Sentinel提供了三个衡量条件:

咋在200ms内搞定,搞不定就1秒中内关闭匝道

异常比例:当资源的每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,即在接下的 时间窗口(以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0]。

在异常比例超过0.2,未来的1秒内不可用

异常数 :当资源近 1 分钟的异常数目超过阈值之后会进行服务降级。注意由于统计时间窗口是分钟级别的,若时间窗口小于 60s,则结束熔断状态后仍可能再进入熔断状态。

在异常数超过5个时,未来的70秒内不可用

5、热点规则

热点参数流控规则是一种更细粒度的流控规则, 它允许将规则具体到参数上。

简单来说就是,参数只要QPS超过每秒n次,马上降级处理

eg:

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                         @RequestParam(value = "p2", required = false) String p2) {
    //int age = 10/0;
    return "------testHotKey";
}
​
public String deal_testHotKey(String p1, String p2, BlockException exception) {
    return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
}

访问路径是testHotKey时,如果参数只要QPS超过每秒n次,马上降级处理,调用deal_testHotKey方法。(超过一秒一下就寄了,参数索引就是参数的下标)

将p1去掉,剩下p2,快速访问,http://localhost:8401/testHotKey?p2=1,发现没有作出限制,这是就要配置参数例外项

当我们p1=5时,就会有问题,http://localhost:8401/testHotKey?p1=5

6、系统规则

属性作用
value资源名称
entryTypeentry类型,标记流量的方向,取值IN/OUT,默认是OUT
blockHandler处理BlockException的函数名称,函数要求: 1. 必须是 public 2.返回类型 参数与原方法一致 3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。
blockHandlerClass存放blockHandler的类,对应的处理函数必须static修饰。
fallback用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求: 1. 返回类型与原方法一致 2. 参数类型需要和原方法相匹配 3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。
fallbackClass存放fallback的类。对应的处理函数必须static修饰。
defaultFallback用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常进行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求: 1. 返回类型与原方法一致 2. 方法参数列表为空,或者有一个 Throwable 类型的参数。 3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定 fallbackClass 里面的方法。
exceptionsToIgnore指定排除掉哪些异常。排除的异常不会计入异常统计,也不会进入 fallback逻辑,而是原样抛出。
exceptionsToTrace需要trace的异常

在实际开发当中经常出现,服务限流,但是超出规则的默认返回提示,这样不太符合业务逻辑。

所以就有了兜底方法。

注:千万注意,兜底的方法的参数,和原来方法的参数必须一致,并且兜底的方法里面需要增加一个【BlockException exception】参数。定义全局兜底的类,里面写如全局兜底的方法,注意,返回类型,参数,一致,且都需要添加异常类,并且方法的修饰符必须是public

6.1、代码

 @GetMapping("/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException")
    public CommonResult byResource() {
        return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial001"));
    }

    public CommonResult handleException(BlockException exception) {
        return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
    }

6.2、效果

sentinel默认的错误信息是:Blocked by Sentinel (flow limiting);如何自定义一个错误信息呢?

6.3、代码

 @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                             @RequestParam(value = "p2", required = false) String p2) {
//        int age = 10/0;
        return "------testHotKey";
    }
​
    public String deal_testHotKey(String p1, String p2, BlockException exception) {
        return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
    }
​

6.4、添加流控规则

6.5、触发效果

我们将// int age = 10/0; 取消注释跑一下

报错了

7、熔断

直接贴代码

@RestController
@Slf4j
public class CircleBreakerController
{
    public static final String SERVICE_URL = "http://nacos-payment-provider";
​
    @Resource
    private RestTemplate restTemplate;
​
    @RequestMapping("/consumer/fallback/{id}")
//    @SentinelResource(value = "fallback") //没有配置
//    @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
//    @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
            exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
​
        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }
​
        return result;
    }
    //本例是fallback
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
    }
    //本例是blockHandler
    public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
    }
​
    //==================OpenFeign
    @Resource
    private PaymentService paymentService;
​
    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        return paymentService.paymentSQL(id);
    }
}
​

id为1看看

我们这里id只有1,2,3数据,其他的都会报错,例如这样的错

用户使用时,肯定不会显示这样的错误信息,但我们配置之后,哪怕出错了,都可以更好的解决

注:fallback只负责业务异常,blockHandler只负责sentinel控制台配置违规

四、规则持久化

1、规则丢失

2、如何做?

然后添加流控规则

重启一下,规则还在,我们的持久化成功了。

举报

相关推荐

0 条评论