Sentinel的原理与应用

目录

一、Sentinel介绍

首先附上官方文档地址

Sentinel是为了解决两个核心问题

  • 流量控制

  • 熔断降级

二、Sentinel安装

具体可参考官方文档

  1. 下载jar包,下载地址

  2. 执行命令java -jar sentinel-dashboard-1.8.7.jar启动sentinel服务,默认端口号为8080

  3. 登录,从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel。

    这就算启动成功了。

三、Sentinel初体验

  1. 项目中导入依赖
xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. 在需要限流、降级的资源上添加@SentinelResource注解

思考:@SentinelResource注解需要打在什么样的资源上?

java 复制代码
@GetMapping("/info")
@SentinelResource("info")
public String getInfo() {
    return info;
}
  1. 在项目中添加dashboard配置
yml 复制代码
spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: localhost:8080

启动项目后调用一下资源,就可以在dashboard看到应用了

四、Sentinel流控规则

QPS限制 - 快速失败

设置单机阈值为1,代表每秒只能有一个请求命中该资源,第二个请求会直接失败

QPS限制 - Warm Up

预热时长代表十秒后预热到每秒支持10QPS,适用于冷启动。

QPS限制 - 排队等待

单机阈值为2代表每500ms处理一个资源请求,设置了超时时间为500ms意思是如果一个请求需要等待超过500ms就会直接报错。

QPS限制 - 关联 - 快速失败

首先,我们新加一个资源

java 复制代码
@GetMapping("/dep")
@SentinelResource("dep")
public String getDep() {
    return "dep";
}

添加关联规则 ,表示如果info所关联的资源dep超过了阈值,则info会被限制访问,访问dep不会报错,但访问info会报错。

QPS限制 - 链路 - 快速失败

链路模式表示从链路入口限流,具体参考文档

新添加一个common资源,从两个入口访问。

java 复制代码
// resource
@Service
public class OrderServiceImpl implements OrderService {
    @Override
    @SentinelResource("common")
    public String common() {
        return "common";
    }
}
// controller 
@GetMapping("/aaa")
public String getAaa() {
    return orderService.common();
}
@GetMapping("/bbb")
public String getBbb() {
    return orderService.common();
}

但是目前所有的资源入口都是sentinel_spring_web_context,不能把aaa和bbb分开。

解决方案 添加如下配置,关闭聚合入口

yml 复制代码
spring:
  cloud:
    sentinel:
      web-context-unify: false

最外层的入口就变为了controller层的入口

此时添加链路限制

访问aaa时成功限流,访问bbb时则无限流。

并发线程数 - 快速失败

单机阈值设置为1,表示同时只能有一个线程处理该资源,可通过thread.sleep测试。

五、Sentinel熔断降级

熔断、降级介绍

要知道为什么需要熔断、降级,我们需要先了解一下服务雪崩。

服务雪崩:因为某一个服务出现问题,导致其他服务,甚至整个系统崩溃的情况,就可以称为服务雪崩。

  • 降级:针对一些资源,提供一个降级方法,当这个资源出现一些问题时,可以快速失败,执行降级方法,返回托底数据。
  • 熔断 :就是针对某个资源提供断路器,有Closed、Open、Half Open状态,是触发降级的手段之一

Closed:代表资源正常,可以访问。(默认状态)

Open:资源出现问题(错误率达到阈值),访问时直接快速失败,执行降级方法,返回托底数据

Half Open:尝试请求资源(Open状态持续5s后,将断路器修改为Half Open状态):

  • 如果处理正常,状态修改为Closed。
  • 如果处理失败,状态修改为Open。

熔断规则

添加测试代码:

java 复制代码
@GetMapping("/circuit-breaker")
public String circuitBreaker(@RequestParam String value) throws InterruptedException {
    switch (value) {
        // 模拟超时
        case "1":{
            Thread.sleep(1000);
            break;
        }
        // 模拟异常
        case "2":{
            int i = 1/0;
            break;
        }
    }
    return "circuit-breaker success";
}
  • 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

    多次调用后出现默认降级:

  • 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

多次请求后由返回错误信息变为返回默认降级:

  • 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

降级方法

使用@SentinelResource注解来绑定降级方法

  • blockHandler:
    • 对应处理BlockException的函数名称
    • 函数访问范围需要时public
    • 返回类型需要和原方法相匹配, 并且最后加一个额外的参数,类型为 BlockException
    • 函数默认和原方法在同一个类中
java 复制代码
@GetMapping("/circuit-breaker")
@SentinelResource(value = "circuit-breaker", blockHandler = "circuitBreakerFallback")
public String circuitBreaker(@RequestParam String value) throws InterruptedException {
    switch (value) {
        // 模拟超时
        case "1": {
            Thread.sleep(1000);
            break;
        }
        // 模拟异常
        case "2": {
            int i = 1 / 0;
            break;
        }
    }
    return "circuit-breaker success";
}
// 必须是BlockException 
public String circuitBreakerFallback(String value, BlockException ex) {
    return "circuit-breaker fallback " + ex.getMessage();
}

普通异常不会处理:

添加限流规则

https://sentinelguard.io/zh-cn/docs/annotation-support.html

热点规则

Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。

  1. 添加测试代码
java 复制代码
@GetMapping("/order/hot")
@SentinelResource(value = "hot")
public String hot(String userId, Integer type){
    return "userId:" + userId + " type:" + type;
}
  1. 在sentinel dashboard界面添加新的热点规则

Note: 热点规则只支持基本参数类型,不支持复合结构类型。支持@PathVariable @PathParam两种参数方式。

授权规则

黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。

Note:通常用于只开放给gateway服务的接口资源

  1. sentinel通过RequestOriginParser获取origin的值并且没有默认实现,所以先添加RequestOriginParser实现类。
java 复制代码
package com.hxd.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class SentinelRequestOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String origin = request.getHeader("origin");
        return origin == null ? "" : origin;
    }
}
  1. 添加测试api
java 复制代码
@GetMapping("/order/author")
@SentinelResource(value = "author")
public String author(){
    return "author!";
}
  1. 添加授权规则,只有appA才能访问该资源
  2. 使用postman访问,并在请求头中添加origin:appA,访问成功。

系统规则

系统规则支持以下的阈值类型:

  • Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
  • RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

六、Sentinel规则持久化

通过官网可以得知我们可以通过两种方式修改规则:

  • 通过 API 直接修改 (loadRules) (只接受内存态)
  • 通过 DataSource 适配不同数据源修改**(对接任意配资源)**

DataSource 扩展常见的实现方式有:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
  • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

推模式:使用 Nacos 配置规则

  1. 导入依赖
xml 复制代码
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  1. 在项目中添加配置
yml 复制代码
spring:
    sentinel:
      datasource:
        flow:
          nacos:
              data-id: ${spring.application.name}-flow.json
              group-id: SENTINEL_GROUP
              data-type: json
              rule-type: flow
              server-addr: ${spring.cloud.nacos.config.server-addr}
  1. 在nocas中添加配置文件

Note: JSON格式最外层需要加大括号,否则不生效。JSON中需要的配置属性可以在AbstractRule类中找。

七、OpenFeign整合Sentinel

  1. 开启配置
xml 复制代码
feign.circuitbreaker.enabled=true
  1. 创建Fallback类
java 复制代码
package com.hxd.client.fallback;

import com.hxd.client.StockClient;
import org.springframework.stereotype.Component;

@Component
public class StockClientFallback implements StockClient {
    @Override
    public String getStock() {
        return "stock fallback method!";
    }
}
  1. 在@FeignClient注解中指定fallback类
java 复制代码
@FeignClient(value = "stock", fallback = StockClientFallback.class)
public interface StockClient {

    @GetMapping("/test/stock")
    String getStock();

}
相关推荐
liushangzaibeijing5 小时前
sentinel动态规则和持久化
sentinel·规则持久化·动态规则
liushangzaibeijing9 小时前
Sentinel组件学习使用
sentinel·限流·熔断·服务降级
我是一只小青蛙8889 小时前
分布式流量守卫者:Sentinel深度解析
分布式·sentinel
廋到被风吹走3 天前
【Spring】Spring Cloud Gateway 网关架构深度解析:路由、过滤器、限流与 Sentinel 集成
spring·架构·sentinel
xiaolyuh1234 天前
Alibaba Sentinel 全解析
系统架构·sentinel·限流
9***g6874 天前
SpringCloud Gateway 集成 Sentinel 详解 及实现动态监听Nacos规则配置实时更新流控规则
spring cloud·gateway·sentinel
DKunYu6 天前
9.熔断和限流 - Alibaba Sentinel
spring cloud·微服务·sentinel
南屿欣风7 天前
Sentinel 资源异常处理优先级笔记
spring boot·笔记·sentinel
lllsure10 天前
Alibaba Sentinel
微服务·sentinel