Sentinel应用笔记

概念

Sentinel应用笔记_第1张图片
当A、B、G、H掉线,其他服务就没法通信了
Sentinel应用笔记_第2张图片

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。
Sentinel应用笔记_第3张图片

特性:

富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Sentinel应用笔记_第4张图片
主要用途:围绕资源的实时状态设定规则,所有规则都可以进行动态实时调整。如服务降级熔断、系统流量控制、系统自适应过载保护等。
Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException)。
Sentinel应用笔记_第5张图片

熔断、降级、限流

熔断

服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。
停止是说,当前服务一旦对下游服务进行熔断,当请求到达时,当前服务不再对下游服务进行调用,而是使用设定好的策略(如构建默认值)直接返回。
暂时是说,熔断后,并不会一直不再调用下游服务,而是以一定的策略(如每分钟调用 10 次,若均返回成功,则增大调用量)试探调用下游服务,当下游服务恢复可用时,自动停止熔断。

降级

降级是指当自身服务压力增大时,采取一些手段,增强自身服务的处理能力,以保障服务的持续可用。比如,下线非核心服务以保证核心服务的稳定、降低实时性、降低数据一致性。
为了预防某些功能出现负荷过载或者响应慢的情况,在其内部暂时舍弃一些非核心接口和数据的请求(如评论、积分),而直接返回一个提前准备好的 fallback(退路) 错误处理信息。释放CPU和内存资源,以保证整个系统的稳定性和可用性。
所谓熔断降级就是为了解决微服务之间调用后产生的异常问题,如A调用了B,而B是微信支付或其他第三方的接口,由于当时的网络原因导致B的响应时长增加,从而造成调用方A的线程池被占用,极端情况下,A的线程池被耗尽,整个服务雪崩。
QPS是对请求的数量进行控制,而无法对于进入服务内的请求是否异常进行控制,熔断降级就是对进入服务之中的请求是否异常来进行控制,从而保护我们的服务。
所以当某个资源的响应时间的线程超过设定线程的阈值时,对于其可以进行熔断降级处理,暂时得关闭访问,熔断器open,当熔断时长到达之后,熔断器进入half-open状态,允许一个请求进入,无论该请求是否正常都会返回,然后如果这个请求正常则熔断器close,如果这个请求异常则熔断器继续open,继续熔断,反复上述步骤。

限流

限流是指上游服务对本服务请求 QPS 超过阙值时,通过一定的策略(如延迟处理、拒绝处理)对上游服务的请求量进行限制,以保证本服务不被压垮,从而持续提供稳定服务。常见的限流算法有滑动窗口、令牌桶、漏桶等。

docker安装Sentinel

docker pull bladex/sentinel-dashboard:1.8.0

docker run --name sentinel --restart=always -d  -p 8858:8858  bladex/sentinel-dashboard:1.8.0

账号/密码都是 sentinel

Sentinel应用笔记_第6张图片

项目中应用

注册到sentinel(服务监控)

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2021.1</version>
</dependency>
spring:
  cloud:
    sentinel:
      transport:
        client-ip: 192.168.56.1
        dashboard: 192.168.56.10:8858    //sentinel  仪表盘地址
        port: 8719    //默认 sentinel api 端口

Sentinel应用笔记_第7张图片

实时监控

感觉不需要有这个也可以实时监控啊

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Actuator默认情况下,只有/info和/heath端点是启用的。因为Actuator本身没有保护,所以大多数端点默认是禁用的,需要我们来选择对外暴露哪些端点。通过这2个属性management.endpoints.web.exposure.include和management.endpoints.web.exposure.exclude(排除哪些)。通过management.endpoints.web.exposure.include属性,可以指定哪些端点想要暴露出来。
我理解的端点指的是需要监控的API接口

management:
  endpoints:
    web:
      exposure:
        include: '*'

Sentinel应用笔记_第8张图片

限流

流控规则

Sentinel应用笔记_第9张图片
流控规则主要分为QPS 和 线程数两大控制方向, 而其后的处理方式有: 直接,关联,链路三种方式,处理效果又分为:快速失败,Warm Up(冷启动),匀速排队。

  • QPS (Query per second) : 即每秒的请求数量

  • 线程数: 即服务中的并发量,值得注意的是,线程数就是并发量,而QPS不一定是并发量,如QPS为1000,而由于服务的耗时操作少,线程执行后归还到线程池的速度快,可能只需要10个线程即可完成,所以要明确QPS与线程数的区别

  • 直接: 顾名思义,即是直接进行接下来的操作,是对被保护的服务进行操作

  • 关联: 在关联资源触碰到阈值时对被保护资源进行操作

  • 链路: 在多个调用中,针对某一条调用链路进行操作,如果触碰到阈值,则该条链路无法访问请求的资源

  • 快速失败: 直接拒绝请求

  • Warm Up: 冷启动,如果启动需要耗时操作时可以如此设置,防止在刚开始进行耗时操作时过多的访问压垮服务,而给与一定的时间进行预热,之后达到处理峰值

  • 匀速排队: 是为了针对访问在不同的时间内,访问量不同,因此设置一个时间长度,来匀速的处理请求,实现削峰填谷,让程序平稳的进行,使用到了漏桶算法,值得注意的是该处理方式不支持QPS> 1000 的场景

    访问某个资源超过阈值时,该资源被保护不让访问
    
      我理解warm up 作用预防在于再短时间内一下子过多qps导致压垮服务
      在服务启动时,对该资源直接进行流控操作,在某段预热时长(单位秒)内,慢慢达到设定的阈值,期间超出的部分直接拒绝,如此达到保护目标资源的目的,Warm Up 的起始值为设定阈值的 1/3(如设定300,则起始阈值为100
    在访问目标资源时,由于访问在不同时间段内的访问量不同,设置此操作
    在设定的时间段内(单位:毫秒),处理 阈值 个数的请求 , 每一个请求的处理时间为: 设置的超时时间 / 阈值
    
    如果关联资源的QPS超过阈值,则被保护资源拒绝访问
    注意点: 关联资源之间不一定就是调用关系,可能并没有关系,而设置之后是控制关联资源的QPS阈值来限制目标资源的访问权限
    
    也是对关联资源在超过设定的QPS阈值时,对目标资源进行冷启动处理,初始阈值依然是设定阈值的 1/3
    而后在预热时长内达到设定阈值,预热时间内超出阈值的请求直接快速失败
    
    关联资源在超过设定阈值时,对于目标资源进行匀速排队的操作
    
    machine-root
       /       \
      /         \
    Entrance1     Entrance2
     /             \
    /               \
    DefaultNode(nodeA)   DefaultNode(nodeA)
    

针对同一个资源有两个入口,Entrance1 和Entrance2 ,他们都调用了同一个资源nodeA,那么这样就形成了一个链路,对此,我们可以设置入口资源为Entrance1 或 Entrance2 中的一个,表示在某一个入口的QPS值达到阈值之后,切断这条链路,使该入口无法被访问

```java
上述介绍的冷启动和匀速排队的策略相同,只是针对的是链路中的某一个入口达到QPS阈值之后的操作

线程数超过阈值的操作一致

降级规则

Sentinel应用笔记_第10张图片

最大 RTResponse Time) : 响应时间,就是在规定什么叫做 “慢” , 单个请求的响应时长大于我们设定的最大RT,那么这个请求就叫做 “慢请求”

比例阈值: 响应时间大于设定RT的线程占总请求数的比例,取值0.0~1.0之间

熔断时长: 达到阈值之后服务请求拒绝的时长(单位:秒)

最小请求数: 1秒钟内发出的最少需要的请求的总数量
解读: 如果一秒钟内发送了5个请求,而其中 比例阈值 * 最小请求数 的个数的请求超过了最大RT 的时间,那么目标资源就会被熔断降级,熔断时长单位为秒。

断路器的工作流程:
1、达到熔断的阈值之后,断路器的状态为open
2、熔断时长内所有的请求都被拒绝,无法进入
3、熔断时长之后,断路器的状态变为half-open,此时允许一个请求进来
4、若该请求没有异常,则断路器的状态为close,之后回归正常
5、若该请求依然异常,则断路器再次变为open状态,所有请求无法进入,等待下一次熔断时长之后

Sentinel应用笔记_第11张图片
Sentinel应用笔记_第12张图片

热点规则

Sentinel应用笔记_第13张图片

授权规则

Sentinel应用笔记_第14张图片

熔断降级fegin托底

@FeignClient(value = "mall-member", fallback = MemberFeginServiceFallBack.class)
@Component
public interface MemberFeginService {


    @PostMapping("/mallmember/member/register")
    public R register(@RequestBody UserRegisterVO userRegisterVO);

    @PostMapping("/mallmember/member/login")
    public R login(@RequestBody LoginVO loginVO);
}
/**
 * @author guanglin.ma
 * @date 2024-01-26 13:32
 */
@Component
@Slf4j
public class MemberFeginServiceFallBack implements MemberFeginService {

    Logger logger = LoggerFactory.getLogger(MemberFeginServiceFallBack.class);

    @Override
    public R register(UserRegisterVO userRegisterVO) {
        logger.error("注册失败哦");
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),
                BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }

    @Override
    public R login(LoginVO loginVO) {
        logger.error("登录失败哦");
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),
                BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }
}
feign:
  sentinel:
    enabled: true

Sentinel应用笔记_第15张图片

限流

public class SentinelUrlBlockHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        R r = R.error(500,"访问太快,稍后再试!");
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write(JSON.toJSONString(r));
    }
}

Sentinel应用笔记_第16张图片
Sentinel应用笔记_第17张图片

自定义资源(不前测试没有成功)

// 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
  // 被保护的业务逻辑
  // do something here...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级
  // 在此处进行相应的处理操作
}
// 资源名可使用任意有业务语义的字符串
if (SphO.entry("自定义资源名")) {
    // 务必保证finally会被执行
    try {
        /**
        * 被保护的业务逻辑
        */
    } finally {
        SphO.exit();
    }
} else {
    // 资源访问阻止,被限流或被降级
    // 进行相应的处理操作
}
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.0</version>
</dependency>

@SentinelResource(value = "test1Resource",blockHandler = "test1BlockHandler")
@Override
public String test1() {
    // 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
//        try (Entry entry = SphU.entry("test1Resource")) {
        // 被保护的业务逻辑
        // do something here...
        logger.error("正常访问");
        return "正常访问";
//        } catch (BlockException ex) {
//            // 资源访问阻止,被限流或被降级
//            // 在此处进行相应的处理操作
//            logger.error("限流中");
//            return "限流中";
//
//        }

}

public void test1BlockHandler(BlockException blockException){
    logger.error("限流中");
}

网关流控

Sentinel应用笔记_第18张图片

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
    <version>2021.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2021.1</version>
</dependency>
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 192.168.56.10:8858
        port: 8719
      eager: true

management:
  endpoints:
    web:
      exposure:
        include: '*'

Sentinel应用笔记_第19张图片
控制仪表可能不显示网关的控制列表,我只这么解决的
Sentinel应用笔记_第20张图片

Sentinel应用笔记_第21张图片

持久化

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.8.0</version>
</dependency>
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.56.10:8848 #nacos地址
      config:
        server-addr: 192.168.56.10:8848 #nacos地址 配置中心
        auto-refresh: true # 是否自动刷新,默认为 false
    sentinel:
      transport:
        client-ip: 192.168.56.1
        dashboard: 192.168.56.10:8858
        port: 8719
      eager: true
      # Sentinel 规则持久化
      datasource:
        ds1:
          nacos:
            server-addr: 192.168.56.10:8848
            dataId: test11
            groupId: DEFAULT_GROUP
            data-type: json
#            流控
            rule-type: flow
        degrade:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
  #            降级
            rule-type: degrade
        system:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-system-rules
            groupId: SENTINEL_GROUP
  #            系统
            rule-type: system
        authority:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-authority-rules
            groupId: SENTINEL_GROUP
  #            授权
            rule-type: authority
        param-flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-param-flow-rules
            groupId: SENTINEL_GROUP
  #            热点
            rule-type: param-flow

Sentinel应用笔记_第22张图片

[
  {
    // 资源名
    "resource": "/test",
    // 针对来源,若为 default 则不区分调用来源
    "limitApp": "default",
    // 限流阈值类型(1:QPS;0:并发线程数)
    "grade": 1,
    // 阈值
    "count": 1,
    // 是否是集群模式
    "clusterMode": false,
    // 流控效果(0:快速失败;1:Warm Up(预热模式);2:排队等待)
    "controlBehavior": 0,
    // 流控模式(0:直接;1:关联;2:链路)
    "strategy": 0,
    // 预热时间(秒,预热模式需要此参数)
    "warmUpPeriodSec": 10,
    // 超时时间(排队等待模式需要此参数)
    "maxQueueingTimeMs": 500,
    // 关联资源、入口资源(关联、链路模式)
    "refResource": "rrr"
  }
]
[
  {
      // 资源名
    "resource": "/test1",
    "limitApp": "default",
    // 熔断策略(0:慢调用比例,1:异常比率,2:异常计数)
    "grade": 0,
    // 最大RT、比例阈值、异常数
    "count": 200,
    // 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
    "slowRatioThreshold": 0.2,
    // 最小请求数
    "minRequestAmount": 5,
    // 当单位统计时长(类中默认1000)
    "statIntervalMs": 1000,
    // 熔断时长
    "timeWindow": 10
  }
]
[
  {
      // 资源名
    "resource": "/test1",
    // 限流模式(QPS 模式,不可更改)
    "grade": 1,
    // 参数索引
    "paramIdx": 0,
    // 单机阈值
    "count": 13,
    // 统计窗口时长
    "durationInSec": 6,
    // 是否集群 默认false
    "clusterMode": 默认false,
    // 
    "burstCount": 0,
    // 集群模式配置
    "clusterConfig": {
      // 
      "fallbackToLocalWhenFail": true,
         // 
      "flowId": 2,
      // 
      "sampleCount": 10,
      // 
      "thresholdType": 0,
      // 
      "windowIntervalMs": 1000
    },
    // 流控效果(支持快速失败和匀速排队模式)
    "controlBehavior": 0,
    // 
    "limitApp": "default",
    // 
    "maxQueueingTimeMs": 0,
    // 高级选项
    "paramFlowItemList": [
      {
          // 参数类型
        "classType": "int",
          // 限流阈值
        "count": 222,
          // 参数值
        "object": "2"
      }
    ]
  }
]
[
  {
      // RT
    "avgRt": 1,
    // CPU 使用率
    "highestCpuUsage": -1,
    // LOAD
    "highestSystemLoad": -1,
    // 线程数
    "maxThread": -1,
    // 入口 QPS
    "qps": -1
  }
]
[
  {
    // 资源名
    "resource": "sentinel_spring_web_context",
      // 流控应用
    "limitApp": "/test",
    // 授权类型(0代表白名单;1代表黑名单。)
    "strategy": 0
  }
]

你可能感兴趣的:(sentinel,笔记)