springcloud Alibaba Sentinel学习笔记

前言

本文为尚硅谷周阳《springcloud第二季》视频学习笔记

一、sentinel是什么

分布式系统的流量防护卫兵

1、sentinel和hystrix对比

sentinel

hystrix

单独一个组件可以独立出来

需要程序员手工搭建监控平台

直接界面化的细粒度统一配置

没有一套web界面给我们进行细粒度化的配置

二、sentinel的下载安装运行

1、下载

# github下载链接,按照视频使用1.7版本
https://github.com/alibaba/Sentinel/releases/download/1.7.0/sentinel-dashboard-1.7.0.jar

2、安装运行

# 1、默认端口8080,注意不要被占用,有Java环境
java -jar sentinel-dashboard-1.7.0.jar

# 2、访问localhost:8080,账号密码为sentinel
localhost:8080

三、sentinel初始化监控

1、新建springboot项目

添加如下Maven依赖

        <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--spring web环境-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--nacos开启注册发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--sentinel持久化到nacos-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2、配置application.yml

server:
  port: 8401
spring:
  application:
    name: springcloudAlibaba-sentinel
  cloud:
    nacos:
      discovery:
        # nacos注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        # 默认端口8719,如果被占用+1直到扫描到不被占用的端口
        port: 8719
        # sentinel dashboard地址
        dashboard: localhost:8080

3、启动类开启服务注册发现

@EnableDiscoveryClient
@SpringBootApplication
public class SpringcloudAlibabaSentinelApplication {

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

}

4、编写controller接口

@RestController
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA(){
        return "testA...";
    }

    @GetMapping("/testB")
    public String testB(){
        return "testB...";
    }
}

5、查看sentinel dashboard

启动项目请求接口,刷新sentinel dashboard,懒加载,不请求接口dashboard没有服务列表

四、sentinel流控规则简介

1、实时监控

可以查看接口访问情况

2、簇点链路

可以查看接口及其链路

五、sentinel流控规则详解

1、QPS直接失败

在”簇点链路“菜单可以点击资源名后对应的流控按钮,进入流控编辑页面

也可以直接点”流控规则“菜单新增流控规则

点击上图”高级选项“默认选项如下,填写单机阈值为1,点击新增

请求接口超过流控频率(QPS即每秒请求数)

2、线程数直接失败

当调用该api的线程数达到阈值的时候,进行限流

添加线程数限流规则

超过每秒一次请求接口并没有超出流控提示(单线程)

显然线程数流控与QPS有所区别

QPS

线程数

解读

关门打狗

御敌于国门之外

理解

拦截请求

接收请求,但是只能处理指定配置阈值。好比银行柜台,银行进来很多客人,但是只有一个柜台,就只能处理一个人的业务,其他的虽然进入银行,但是不处理

多线程下,如果有线程在被处理,已经到达阈值,其他线程请求会提示超出流控

3、关联流控

当关联的资源A达到阈值时,就限流B(我感冒你吃药)

如:当支付接口达到阈值,可以限流下订单接口

使用postman模拟并发阈值访问

testA接口由可以正常访问变为限制访问

直到testB接口访问结束(不超出设定阈值)后,testA访问正常

4、预热

快速失败直接抛出异常

查看源码来源于com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController

预热公式:阈值除以冷加载因子(coldFactor(默认3))

经过预热时长才达到阈值

此场景用于避免接口瞬间大幅度提升请求,导致系统打垮

配置如下:

解读:阈值为10÷3(冷加载因子)取整=3,即从QPS3~10需预热五秒钟

源码来自于:

com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController#WarmUpController(double, int)

5、排队等待

匀速排第,让请求以均匀的速度(严格,漏桶算法)通过,阈值类型必须设成QPS,否则无效

思路:拒绝”忙得时候忙死,闲的时候闲死“

配置如下:

解释:testA每秒一次请求,超过就排队,等待超时时间为20秒

源码:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

使用postman发送每秒一次接口请求,后台日志结果

六、熔断降级

熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高)

对这个资源进行限制,让它快速响应失败

避免影响到其他资源导致级联错误

当资源被降级后,在接下来的时间降级窗口之内,对该资源的调用都自动熔断

默认行为抛出DegradeException

sentinel的断路器没有半开状态

半开状态解释:hystrix会检查请求是否有异常,有就打开断路器,没有就关闭断路器

1、RT(平均响应时间)

解释:秒级,RT超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足时触发降级

窗口期过后关闭断路器

RT最大4900(更大的需求通过-Dcsp.sentinel.statistic.max.rt=xx设置虚拟机参数生效)

配置:

代码接口模拟一秒处理请求响应

jmeter模拟1秒钟10个线程请求

显然接口testB处理不了一秒钟10个请求,只能一秒钟一个

开启jmeter,请求接口发现接口被熔断

待关闭jmeter后,请求正常响应

2、异常比例

解释:秒级,QPS>=5且异常比例(秒级统计)超过阈值时,触发降级

时间窗口结束后,关闭降级

配置:

接口代码模拟超过异常比例:

jmeter模拟一秒钟10个请求

请求接口,已经熔断保护

停止jmeter,请求接口,抛出错误

3、异常数

解释:分钟统计,超过阈值时,触发降级

时间窗口结束后,关闭降级

配置:

需要注意的是,统计时间为分钟级

如果时间窗口小于60s,结束窗口期,仍可能进入熔断降级

配置时间窗口时间要大于60s

代码:

请求接口五次异常以后,熔断降级

带时间超过窗口期时间,请求异常

七、热点规则限流

解释:

很多时候我们希望根据某些热点数据访问频次高的数据进行限制

如:苹果新发布手机,超话等

热点参数限流会根据传入的热点参数,单独限制流控

只对该热点参数的某些值进行限制

热点限流源码:

com.alibaba.csp.sentinel.slots.block.BlockException

限流的总体思想:

        try {
            // 逻辑符合限流规则
        } catch (Exception e) {
            // 进入限流
        } finally {
            
        }

1、热点规则

热点限流配置:

代码:

第一个参数p1不为空,请求频率超过一秒1次,执行兜底方法

请求第二个参数p2,不受影响

如果代码没有配置兜底方法

超过限流规则,则正常打出错误日志

需要注意的是,只要含有指定限流规则的参数就会执行兜底,后面可以继续加别的参数

2、参数例外项

解释:即VIP通道

配置:

代码不变,请求接口超过1秒一次,但传入的参数为例外项,没有超出阈值,则没有执行限流

参数例外项支持一下七种参数类型

值得注意的是@SentinelResource不会影响代码正常的异常,没有超出限流仍会有异常抛出

八、系统规则

解释:即系统自适应限流

从整体的维度对应用入口流量进行配置

”防疫一刀切“(粒度变小)

配置:

系统规则

各个阈值类型解释:

a,LOAD自适应(仅对Linux/unix-like机器生效):系统的load1作为启发指标,进行自适应系统保护。

当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段)

系统容量由系统的maxQpsminRt估算得出。设定参考值一般是CPU cores*2.5

b,CPU usage(1.5.0+版本):当系统CPU使用率超过阈值即触发系统保护(取值范围0.0~1.0),比较灵敏。

c,平均RT:当单台机器上所有路口流量的平均RT达到阈值即触发系统保护,单位是毫秒。

d,并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。

e,入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护。

九、@SentinelResource配置

对标@HystrixCommand

1、 三种配置方案及区别

代码如下:

@SentinelResource和兜底代码

a,若点击此按照配置限流规则

按照/接口名设置流控规则

流控规则

此时超过限流访问接口不会执行兜底方法

超出限流执行结果

b,若按照@SentinelSource注解的value值配置

按照@SentinelSource注解value值配置

新增流控配置

超过流控后执行了兜底方法

c,如果没有兜底方法配置,且流控配置为@SentinelSource的value值

代码:

没有兜底方法配置

配置:

配置资源名为@SentinelResource的value

超出限流规则后:

超出流控

2、上述兜底方法面临的问题

a,系统默认的,没有体现我们自己的业务要求

b,依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观

c,每个业务方法都添加一个兜底的,那代码膨胀加剧

d,全局统一的处理方法没有体现

十、客户自定义限流处理逻辑

编写统一处理限流异常类,注意方法有static和入参BlockException

代码:

统一处理限流异常类

此时业务接口@SentinelResource注解的值,可以按照需要配置

blockHandlerClass的值为限流异常处理类

blockHandler为异常处理的具体方法

代码:

@SentinelResource属性值

配置:

流控配置

请求超出配置后执行结果:

执行结果

以上解决了兜底方法面临的问题,解耦处理、

注意:注解埋点不支持private方法

十一、 编写代码方式配置限流

不推荐,略

十二、sentinel在openFeign下熔断配置

1、搭建一个简单的openFeign远程调用环境

a,springcloudAlibaba-order(服务提供者)

引入pom依赖:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

启动类:

@EnableDiscoveryClient // 开启服务注册发现
@SpringBootApplication
public class SpringcloudAlibabaOrderApplication {

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

yml:

server:
  port: 8402
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: springcloudAlibaba-order

代码:

@RestController
public class OrderController {

  private static HashMap<Long, String> dao = new HashMap<>();

  static {
    dao.put(1L, "orderDetail...1");
    dao.put(2L, "orderDetail...2");
    dao.put(3L, "orderDetail...3");
  }

  @GetMapping("/orderDetail/{id}")
  public String orderDetail(@PathVariable("id") Long id) {

    return dao.get(id);
  }
}

b,springcloudAlibaba-sentinel(服务消费者)添加配置

pom新增依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

启动类新增注解:

@EnableFeignClients // 新增开启feign远程调用
@EnableDiscoveryClient
@SpringBootApplication
public class SpringcloudAlibabaSentinelApplication {

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

}

yml新增配置:

# 激活sentinel对feign的支持
feign:
  sentinel:
    enabled: true

代码:

新建远程调用feign接口

@FeignClient(value = "springcloudAlibaba-order", 
fallback = OrderFeignServiceFallbackService.class) // 降级实现类
public interface OrderFeignService {

    @GetMapping("/orderDetail/{id}")
    String orderDetail(@PathVariable("id") Long id);
}

降级实现类

@Component // 注意添加注解
public class OrderFeignServiceFallbackService implements OrderFeignService {

    @Override
    public String orderDetail(Long id){

        return "服务降级返回OrderFeignServiceFallbackService...";
    }
}

c,启动两个服务,在nacos可视化工具中查看服务是否注册成功

两个服务注册nacos成功

d,测试远程调用

远程调用成功

2、测试sentinel服务熔断降级

a,模拟服务崩溃,停用服务提供者(springcloudAlibaba-order)

springcloudAlibaba-order服务已被停掉

b,再次发起远程调用,执行服务熔断降级逻辑

服务降级处理

起到了防止服务调用不成功,一直重试卡死的情况

如果需要配置限流和兜底请自行添加@SentinelResource进行测试

需要注意的是fallback为Java异常处理,blockHandler为限流异常处理

十三、sentinel持久化规则

sentinel默认没有持久化配置信息,服务启动配置即消失

sentinel持久化采用结合nacos持久化的方案

将限流配置规则持久化存储到nacos保存

只要nacos配置不删除,则sentinel限流规则持续有效

a,nacos新建sentinel流控配置文件

nacos的sentinel流控配置

其中:

resource:资源名称;

limitApp:来源应用;

grade:阈值类型,0表示线程数,1表示QPS;

count:单机阈值;

strategy:流控模式,0表示直接,1表示关联,2表示链路;

controlBehavior:流控效果,0表示快速失败,1表示warmup,2表示排队等待;

clusterMode:是否集群;

b,增加sentinel持久化nacos的yml配置

spring:
  application:
    name: springcloudAlibaba-sentinel
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: springcloudAlibaba-sentinel
            goupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

c,一定要请求一次(sentinel懒加载)对应流控的接口,方可发现sentinel Dashboard中有配置信息

sentinel Dashboard已经有流控配置信息

d,停掉服务,再次请求配置流控的接口,发现配置信息还在

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值