Sentinel


一、什么是Sentinel

1. 认识Sntinel

Sntinel是阿里巴巴开源的一款微服务流量控制组件。官网地址:点击跳转
特性

  • 丰富的应用场景:秒杀、消息削峰填谷,集群流量控制,实时熔断下游不可以用应用等
  • 完善的实时监控:可在控制台看到接入应用的单机秒级数据、集群的汇总运行情况
  • 广泛的开源生态:与Spring Cloud,Dubbo,gPRC的整合
  • 完善的SPI扩展点:提供了简单易用、完善的SPI扩展接口,可以通过实现扩展接口来快速定制逻辑。例如定制规则管理,适配动态数据源等

2. 为什么要使用Sntinel

  • 微服务雪崩:
    • 概念:微服务调用链路中的某个服务故障,引起整个链路中的微服务都不可用
    • 解决办法:
      • 超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会一直等待
      • 舱壁模式:限定每个业务能使用的线程数,避免耗尽整个timcat的资源,也叫线程隔离
      • 熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求
      • 流量控制:限制业务访问的QPS(每秒处理请求的数量),避免服务因流量的突增而故障

2.1. Sentinel与Hystrix对比

在这里插入图片描述

2.2. Sentinel 的使用可以分为两个部分:

  • 核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持(见 主流框架适配)。
  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。

3. 服务中整合Sentinel

3.1. 控制台

  • 下载地址:https://github.com/alibaba/Sentinel/releases
  • 启动:
    • 注意事项:启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。且不要将jar包放在中文目录下
    • 命令:
      java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
  • 默认账号密码:sentinel

3.2. 整合到Spring服务中

  • 注意:配置完成后在控制台并不会马上看到对应服务,此时我们需要访问该服务中的任意一簇点(接口)后再返回控制台即可查看
  • 在需要Sentinel的服务中按照以下步骤操作
1.引入依赖
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
2. 配置
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8088 
3. 添加sentinel资源(添加簇点/添加资源)
  • Controller层的方法,也就是添加 @RequestMapping系列的方法,会在第一次请求后自动添加到sentinel中
添加额外的资源
  • 在对应的方法或资源添加 @SentinelResource(value="goodsQuery")注解。
  • value属性:资源名称

二、流量控制

添加流控

  • 方式一:在控制台页面选择对应服务–>流控规则–>新增流控规则。
    出现以下页面:
    在这里插入图片描述

  • 资源名:就是在簇点链路页面的资源名

  • 针对来源:从何处来的请求会被限流

  • 阈值类型:

    • QPS:每秒请求数量
    • 并发线程数:每秒最大线程数
  • 单机阈值:数字值,与阈值类型相关

  • 是否集群:

流控模式:

注意事项:对谁限流,就对谁添加限流规则

直接:
  • 统计当前资源的请求,触发阈值时对当前资源直接 限流(默认的模式)
关联:
  • 概念:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
  • 使用场景:当多个业务使用或竞争同一资源时,将优先级高的业务与其他业务进行关联。
  • 效果:当优先级高的业务被大量请求时,对另一业务进行限流
  • 配置示例:
    • 订单支付业务和订单查询订单,当用户支付完成后,需要修改订单状态,但同时也会有用户进行订单查询。
    • 支付业务优先于查询业务,所以对查询业务添加限流规则,当支付业务流量大时,对查询业务进行限流
    • 如下图:
链路:
  • 概念:统计从指定链路访问到泵资源的请求,触发阈值时,对指定链路限流
  • 使用场景:当多个业务使用或竞争同一资源时,监控优先级别低的业务。
  • 效果:当优先级低的业务有大量请求时,对该业务进行限流,从而保证资源的正常访问(保证了其他调用此资源的业务正常进行)
  • 配置示例:
    • 创建订单和查询订单业务,两者都需要查询商品
    • 创建业务优先于查询业务,针对查询订单进入到查询商品的请求设置限流,从而保证创建订单业务正常进行
    • 如下图
      在这里插入图片描述

流控效果:

快速失败
  • 概念:达到阈值后,新的请求会立刻被拒绝并抛出FlowException异常(默认方式)
warm up
  • 概念:预热模式,对超出阈值的请求同一是拒绝并抛出异常,但这种模式阈值会动态变化,从一个较小的值逐渐增加到最大阈值,请求阈值的初始值是 最大阈值(threshold) / 冷启动因子(coldFactor) 。持续指定时长后,逐渐提高到最大阈值,冷启动因子(coldFactor)的默认值是3
  • 使用场景:应对服务冷启动的一种方案
排队等待
  • 概念:让所有请求按照先后次序排队执行,如果请求预期的等待时间超出最大时长,则会被拒绝并抛出异常。
  • 使用场景:流量削峰

热点参数限流

  • 概念:分别统计参数值相同的请求,判断是否超过QPS阈值
  • 注意:热点参数限流对默认的SpringMVC资源无效
  • 使用场景:需要更细粒度的限流
  • 配置示例:
    • 在控制台页面选择对应服务–>热点规则–>新增热点限流规则。
    • 参数类型只有基本数据类型和String,如果参数属于这几种的话是无法进行热点参数限流的
      在这里插入图片描述

三、隔离和降级

  • 虽然限流可以尽量避免因高并发引起的服务故障,但服务还会以为卡原因故障。而要将这些故障控制在一定范围,避免雪崩,就要靠线程隔离(舱壁模式)和熔断降级手段了。
  • 不管是线程隔离还是熔断降级,都是对 客户端(调用方) 的保护

FeignClient整合Sentinel

在SpringCloud中,微服务调用都是通过Feign实现的,因此做客户端保护必须整个Feign和Sentinel

  1. 修改服务中的yml文件,开启Feign的Sentinel功能
feign:
  sentinel:
    enabled: true  #开启Feign的Sentinel功能
  1. 给FeignClient编写失败后的降级逻辑
    • 方式一:FallbackClass,无法对远程调用的异常做处理
    • 方式二:FallbackFactory,可以对远程调用的异常做处理(使用这种)

实现FallbackFactory

1、编写失败降级逻辑
@Slf4j
public class PayFeignFallbackFactory implements FallbackFactory<PayFeign> {
    @Override
    public PayFeign create(Throwable throwable) {
        /**
         * 创建一个PayFeign对象,在对应方法中直接编写失败降级逻辑
         */
        return new PayFeign() {
            @Override
            public boolean payStatus() {
                log.error("查询支付状态异常");
                return false;
            }
        };
    }
}
2、将实现的FallbackFactory注册为bean
@Configuration
public class FallbackConfig {
    @Bean
    public PayFeignFallbackFactory payFeignFallbackFactory() {
        return new PayFeignFallbackFactory();
    }
}
3、在对应的@FeignClient注解添加参数 fallbackFactory
@FeignClient(value = "pay", fallbackFactory = PayFeignFallbackFactory.class)
public interface PayFeign {

    @GetMapping(value = "/payStatus")
    boolean payStatus();

}

线程隔离(舱壁模式)

使用线程隔离时,限流规则处选择并发线程数即可
在这里插入图片描述

  • 线程池隔离
    • 优点:支持主动超时、支持异步调用
    • 缺点:线程的额外开销比较大
    • 场景:适合低扇出
  • 信号量隔离(Sentinel默认采用)
    • 优点:轻量级,无额外开销
    • 缺点:不支持主动超时、不支持异步调用
    • 场景:适合高扇出、高频调用
      在这里插入图片描述

熔断降级

  • 熔断降级是解决雪崩问题的重要手段。断路器统计服务调用的异常比例,慢请求笔记,如果超过阈值则会熔断该服务。及拦截访问该服务的一切请求,当服务恢复时,断路器会方向访问该服务的请求。
    在这里插入图片描述
  • 断路器熔断策略有三种:慢调用、异常比例、异常数
  • 在控制台页面选择对应服务–>熔断规则–>新增熔断规则。

慢调用

  • 解释:业务响应时长(RT)大于指定时长的请求被认定为慢调用请求。在指定时间内,请求数量超过设定的最小数量,满调用比例大于设定的阈值,则触发熔断
  • 案例:RT超过50ms的调用是慢调用,统计最近10000ms内的请求,如果请求量超过10次并且慢调用比例大于50%,则触发熔断,时长为5秒。5秒后进入 Half-Open状态,放行一次请求进行测试
    在这里插入图片描述

异常比例/异常数

  • 解释:统计指定时间内的调用,如果调用次数超过指定请求数并且出现的异常比例达到设定的比例阈值(或超过指定异常数),则触发熔断
  • 案例:
    • 异常比例:统计最近1000ms内的请求,如果请求量超过10次并且异常比例大于50%,则触发熔断,时长为5秒。5秒后进入 Half-Open状态,放行一次请求进行测试
      在这里插入图片描述

    • 异常数:统计最近1000ms内的请求,如果请求量超过10次并且异常数量大于5,则触发熔断,时长为5秒。5秒后进入 Half-Open状态,放行一次请求进行测试
      在这里插入图片描述

四、授权规则

  • 授权规则可以对调用方的来源做控制,有白名单和和黑名单两种方式
    • 白名单:来源(origin)在白名单内的调用者允许访问
    • 黑名单:来源(origin)在黑名单内的调用者不允许访问
  • Sentinel是通过RequstOrginParser这个接口的parseOrigin来获取请求的来源的。但是获取到的数据一般都是undefined 不起作用,此时需要自己实现
  1. 实现 RequstOrginParser 接口并重写parseOrigin方法
@Component
public class HeaderOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest httpServletRequest) {
        //1.获取请求头
        String origin = httpServletRequest.getHeader("origin");
        //非空判断
        if (StringUtils.isEmpty(origin)) {
            return "blank";
        }
        return origin;
    }
}
  1. 向网关添加默认过滤器 添加头部信息
spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=origin,gateway #originw为头标签,gateway为值
  1. 添加授权规则(以白名单举例)
  • 在控制台页面选择对应服务–>授权规则–>新增授权规则。
    在这里插入图片描述

五、自定义异常结果

  • 默认情况下,发生限流、熔断降级、授权拦截时,都会抛出异常(Blocked by Sentinel (flow limiting))到调用方,但由于所有异常都默认相同,对用户/调用方不友好,起不到提示作用。

  • 所以我们需要自定义异常返回结果,实现BlockExceptionHandler接口即可实现

  • BlockExceptionHandler的子类
    在这里插入图片描述

  • 实现 BlockExceptionHandler接口

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        String msg = "未知异常";
        int status = 429;
        if (e instanceof FlowException) {
            msg = "请求被限流了";
        } else if (e instanceof DegradeException) {
            msg = "请求被降级了";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数被限流";
        } else if (e instanceof AuthorityException) {
            msg = "请求没有权限";
            status = 401;
        }
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.setStatus(status);
        httpServletResponse.getWriter().println("{\"message\":\"" + msg + "\",\"status\":" + status + "  }");
    }
}

六、规则持久化

规则管理模式

  • 原始模式
    Sentinel的默认模式,将规则保存在内存,重启服务会丢失。

  • pull模式
    控制台将配置的规则推送到Sentinel客户端,而客户端会将配置规则保存在本地文件或数据库中,以后会定时去本地文件或数据库中查询,更新本地规则

  • push模式
    控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配置变更的推送消息,完成本地配置更新

实现push模式

push模式实现最为复杂,依赖于nacos,并且需要修改Sentinel控制台源码和微服务。

修改微服务

  1. 引入依赖
<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. 配置nacos地址
spring:
  cloud:
    sentinel:
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: orderservice-flow-rules
            group-id: SENTINEL_GROUP
            rule-type: flow #还可以是degrade、authority、param-flow
        degrade:
          nacos:
            server-addr: localhost:8848
            data-id: orderservice-degrade-rules
            group-id: SENTINEL_GROUP
            rule-type: degrade #还可以是flow、authority、param-flow
  

修改sentinel-dashboard源码

SentinelDashboard默认不支持nacos的持久化,需要修改源码。前往Sentinel官方gitHub下载源码

1、修改nacos依赖
  • 在sentinel-dashboard源码的pom文件中,nacos的依赖默认的scope是test,只能在测试时使用,这里要去除:
    在这里插入图片描述

将sentinel-datasource-nacos依赖的scope去掉:

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
2. 添加nacos支持

在sentinel-dashboard的test包下,已经编写了对nacos的支持,我们需要将其拷贝到main下。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我好帅啊~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值