SpringCloud Alibaba之Sentinel配置

[官方文档]

Spring Cloud Alibaba Sentinel

Sentinel 介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。

同类型产品比较

SpringCloud Alibaba之Sentinel配置_第1张图片

引入依赖

        
  <dependency>
     <groupId>com.alibaba.cloudgroupId>
     <artifactId>spring-cloud-alibaba-dependenciesartifactId>
     <version>2.2.9.RELEASEversion>
     <type>pomtype>
     <scope>importscope>
  dependency>
<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

Sentinel 控制台

Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。您只需要对应用进行简单的配置,就可以使用这些功能。

开启该功能需要3个步骤:

1.下载jar包 (地址: https://github.com/alibaba/Sentinel/releases)

注意:下载的jar包要对应 Spring Cloud alibaba 的版本
SpringCloud Alibaba之Sentinel配置_第2张图片

2.启动控制台

Sentinel 控制台是一个标准的 Spring Boot 应用,以 Spring Boot 的方式运行 jar 包即可。
Sentinel 控制台默认的端口为8080,为避免端口冲突可以通过自定义端口的命令启动.

  java  -jar sentinel-dashboard.jar
  或 
  java -Dserver.port=自定义端口 -Dcsp.sentinel.dashboard.server=IP:自定义端口 -jar sentinel-dashboard.jar

默认用户名:sentinel 默认密码:sentinel
SpringCloud Alibaba之Sentinel配置_第3张图片
SpringCloud Alibaba之Sentinel配置_第4张图片

3.配置控制台信息
server:
  port: 8088
spring:
  application:
    name: sentinel-client
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080

Sentinel控制台规则配置详解

流控规则(通常在Provider 端配置)

流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状.
其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
流量控制主要有两种统计类型,一种是统计并发线程数,另外一种则是统计 QPS。类型由 FlowRule 的 grade 字段来定义。其中,0 代表根据并发数量来限流,1 代表根据 QPS 来进行流量控制。其中线程数、QPS 值,都是由 StatisticSlot 实时统计获取的。
SpringCloud Alibaba之Sentinel配置_第5张图片

使用场景:

控制脉冲流量 针对不用调用来源进行流控 web接口流控
流量控制有以下几个角度:
资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
运行指标,例如 QPS、线程池、系统负载等;
控制的效果,例如直接限流、冷启动、排队等。

如何配置规则:

梳理核心接口 通过事前压测评估核心接口的容量,配置QPS阈值

相关参数

一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:

Field 说明 默认值
resource 资源名,资源名是限流规则的作用对象 直接拒绝
count 限流阈值
grade 限流阈值类型,QPS(1) 或线程数模式(0) QPS 模式
limitApp 流控针对的调用来源 default,代表不区分调用来源
strategy 调用关系限流策略:直接、链路、关联 根据资源本身(直接)
controlBehavior 流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流 直接拒绝
控制台操作界面

SpringCloud Alibaba之Sentinel配置_第6张图片

阈值类型

QPS :指的是在一秒内同时服务的请求数 (并发数)
线程数 : 指同时在处理请求的线程数量

自定义流控返回

当配置了流程参数设置后,程序达到流控上限,会返回下面的提示
SpringCloud Alibaba之Sentinel配置_第7张图片
如果需要自定义放回或是需要在降级之后增加处理逻辑可以通过 @SentinelResource 实现

@SentinelResource

代码示例:

value 对应的是 resource 资源名 需要在控制台中设置流控参数自定义返回开会生效
blockHandler 块异常函数的名称 (使用blockHandler 指定的方法需要在定义在同一个类中)
blockHandlerClass 指定的方法不在同一个类中可以使用blockHandlerClass来指定,但是方法必须声明为static 静态方法,

  /**
    * blockHandlerClass = WebUtil.class
    */
    @RequestMapping(value = "/index",method = RequestMethod.GET)
    @SentinelResource(value = "index",blockHandler = "testBlockHandler")
    public CommonResult test(){
        return new CommonResult("OK");
    }
    //自定义流控返回
    public CommonResult testBlockHandler(BlockException e){
        return new CommonResult("流控");
    }
sentinel统一异常处理

如果不想用 @SentinelResource 注解来处理,则可以采用统一异常处理,如果需要对不同的业务做不同的处理,建议使用 @SentinelResource 注解来处理.
一旦使用了@SentinelResource 注解来处理,统一异常处理就不会被使用,需要另外定义返回

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.car.hailing.saas.base.CommonResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
     //getRule()  规则的详细信息
     log.info("lockExceptionHandler============="+e.getRule());

        CommonResult r = null;

        if (e instanceof FlowException){
            r = new CommonResult<>(100,"接口限流");
        }else if (e instanceof DegradeException){
            r = new CommonResult<>(101,"服务降级");
        }else if (e instanceof ParamFlowException){
            r = new CommonResult<>(102,"热点参数限流");
        }else if (e instanceof SystemBlockException){
            r = new CommonResult<>(103,"出发系统保护规则");
        }else if (e instanceof AuthorityException){
            r = new CommonResult<>(104,"授权规则不通过");
        }

        httpServletResponse.setStatus(500);
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(httpServletResponse.getWriter(),r);

    }
}
/**
 * api rest返回实体
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class CommonResult<T> implements Serializable {

    private int code;

    private String msg;

    private T data;

    /**
     * 默认成功
     */
    public CommonResult()
    {
        this.code = SystemResult.SUCCESS.code;
        this.msg = SystemResult.SUCCESS.message;
    }

    public CommonResult(T t)
    {
        this.code = SystemResult.SUCCESS.code;
        this.msg = SystemResult.SUCCESS.message;
        this.data = t;
    }

    public CommonResult(SystemResult r)
    {
        this.code = r.code;
        this.msg = r.message;
        this.data = null;
    }

    public CommonResult(int r, String t)
    {
        this.code = r;
        this.msg = t;
        this.data = null;
    }

}
3种流控模式

1.直接 模式: 直接模式就是对当前入口直接限流

SpringCloud Alibaba之Sentinel配置_第8张图片

2.关联 模式 : 当关联的资源达到阈值时就会对配置的资源进行限流
比如: 下单接口和查询订单接口,当我们对查询接口设置了流控规则并关联了下单接口,当下单接口的请求数量达到阈值时,就会对查询接口进行限流,这样就能保证下单接口的安全性

SpringCloud Alibaba之Sentinel配置_第9张图片

3.链路模式 : 对调用链路的入口进行限流,Sentinel不仅可以对接口入口进行限流还可以对方法进行限流.
例如 我们通过@SentinelResource 对 方法getUser 进行了限流,通过链路模式关联了接口A,在调用过程中,接口A和接口B都会调用getUser方法,当getUser方法达到调用阈值时,就会对关联的接口A进行限流,而接口B可以不受限制的进行调用.

SpringCloud Alibaba之Sentinel配置_第10张图片
使用链路模式还需要配置一下web-context-unify配置,限流才会生效

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      #展开调用链路, 默认为收起
      web-context-unify: false      
3种流控效果

1.快速失败: 当并发量超过设置的阈值后,超出的请求会被直接拒绝.

SpringCloud Alibaba之Sentinel配置_第11张图片

  1. Warm Up(激增流量) : 流控预热模式有一个预热时长参数,当大量请求过来时,并不是直接处理相当于阈值数量的请求,而是在设置的预热时长内,逐渐递增式的处理请求,直到达到阈值数量.递增初始值的冷加载因子值为设置的阈值除以3.

SpringCloud Alibaba之Sentinel配置_第12张图片

  1. 排队等待(脉冲流量): 相当于队列,当大量请求过来时,超过阈值的请求不会马上拒绝,而是进行排队等待,并提供了一个设置超时时间的参数,在超时时间到期之前,如果前面的请求被出来完,排队等待中的请求会被继续处理

SpringCloud Alibaba之Sentinel配置_第13张图片

熔断降级(通常在consumer端组合配置)

除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和 Hystrix 里面描述的问题是一样的。
SpringCloud Alibaba之Sentinel配置_第14张图片

Sentinel 提供以下几种熔断策略:

慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
SpringCloud Alibaba之Sentinel配置_第15张图片

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

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

注意异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常。

相关参数

熔断降级规则说明
熔断降级规则(DegradeRule)包含下面几个重要的属性:

Field 说明 默认值
resource 资源名,即规则的作用对象
grade 熔断策略,支持慢调用比例/异常比例/异常数策略 慢调用比例
count 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值0~1之间的数
timeWindow 熔断时长,单位为 s
minRequestAmount 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) 5
statIntervalMs 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) 1000 ms
slowRatioThreshold 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

整合Openfeign

1.添加依赖

       
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>

2.开启Openfeign对sentinel支持配置

#开启Openfeign对sentinel的支持默认为false
feign:
  sentinel:
    enabled: true

3.添加对Openfeign接口的实现

public class UserFeignServuceFallback implements UserFeignServuce {
    @Override
    public String test() {
        //TODO 降级操作 实现feign接口的方法 可以在这里做失败处理  比如可以在这里记录降级日志,后续自动补偿
        //比如 积分服务, 在服务降级的请求下,如果积分服务被关闭,无法调用,可以现在这里记录日志,需要添加的用,和对应的积分
        // 可以通过另外的定时任务捞取日志中的失败操作对用户进行补偿
        return null;
    }
}

4.在Openfeign接口添加 fallback 属性,并指向实现类

@FeignClient(value = "manage-client",fallback = UserFeignServuceFallback.class)
public interface UserFeignServuce {

    @RequestMapping(value = "/index/test")
    String  test();
}

热点参数限流

热点参数规则使用必须要配合 @SentinelResource 注解来处理

SpringCloud Alibaba之Sentinel配置_第18张图片

相关参数

热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule):

属性 说明 默认值
resource 资源名,必填
count 限流阈值,必填
grade 限流模式 QPS 模式
durationInSec 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 1s
controlBehavior 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持 快速失败
maxQueueingTimeMs 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持 0ms
paramIdx 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置
paramFlowItemList 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型
clusterMode 是否是集群参数流控规则 false
clusterConfig 集群流控相关配置
控制台操作界面

SpringCloud Alibaba之Sentinel配置_第19张图片

系统保护规则

Sentinel 系统自适应保护从整体维度对应用入口流量进行控制,结合应用的 Load、总体平均 RT、入口 QPS 和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。

相关参数

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

属性 说明
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 达到阈值即触发系统保护
控制台操作界面

SpringCloud Alibaba之Sentinel配置_第20张图片

Sentinel 规则持久化

(为什么要做持久化因为在控制台添加的配置是存在内存中的,当服务重启后会被清除掉)

当使用了nacos配置持久化参数后,如果要修改配置,要通过修改nacos config中添加的sentinel配置来更新,通过操作台添加的配置不能同步到nacos config中.

一般来说,规则的推送有下面三种模式:
SpringCloud Alibaba之Sentinel配置_第21张图片
生产环境一般推荐使用Push模式,通过Nacos来持久化配置

1.引入依赖

      
        <dependency>
            <groupId>com.alibaba.cspgroupId>
            <artifactId>sentinel-datasource-nacosartifactId>
        dependency>

2.在nacos上新建一个sentinel配置文件,默认为json格式
SpringCloud Alibaba之Sentinel配置_第22张图片

[
{
“resource”: “/api/test”,
“count”:2,
“grade”:1,
“limitApp”:“default”,
“strategy”:0,
“controlBehavior”:0
}
]

3.yaml配置sentinel整合nacos持久化配置

spring:
  application:
    name: manage-client
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        username: nacos
        password: nacos
        namespace: public
    sentinel:
      transport:
        dashboard: localhost:8080
      web-context-unify: false
      datasource:
        nacos-sentinel:  #可以自定义
          #可以与多种组件整合使用 file/nacos/zk/apollo/redis/consul
          nacos:
            serverAddr: 127.0.0.1:8847
            username: nacos
            password: nacos
            #自定义了命名空间 可以指定命名空间
            namespace: public
            #自定义了分组,可以指定分组
            groupId: DEFAULT_GROUP
            #对应nacos中添加的sentinel配置的DataID
            dataId: sentinel-config
            #指定规则 flow 流控/degrade 降级/param-flow 热点规则/system系统规则/authority 授权/gw-flow 网关限流
            ruleType: flow

你可能感兴趣的:(sentinel,spring,cloud,java)