Sentinel基础与控制台整合

链接

Sentinel文档

Sentinel 介绍

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
在这里插入图片描述

规则

围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

Sentinel 功能

流量控制

流量控制有以下几个角度:

资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
运行指标,例如 QPS、线程池、系统负载等;
控制的效果,例如直接限流、冷启动、排队等。
Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

熔断降级

Sentinel 和 Hystrix 的原则是一致的: 当调用链路中某个资源出现不稳定,例如 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。
使用场景:通常在弱依赖程序中使用,如积分功能,可以降级写日志,之后再进行增添

熔断降级设计限制的手段
通过并发线程数进行限制、通过响应时间对资源进行降级

系统负载保护

Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。

与Hystrix对比

在这里插入图片描述

快速开始(使用代码的方式实现)

1.引入 Sentinel 依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.5</version>
</dependency>

2.定义资源

资源 是 Sentinel 中的核心概念之一。最常用的资源是我们代码中的 Java 方法。 当然,您也可以更灵活的定义你的资源,例如,把需要控制流量的代码用 Sentinel API SphU.entry(“HelloWorld”) 和 entry.exit() 包围起来即可。在下面的例子中,我们将 System.out.println(“hello world”); 作为资源(被保护的逻辑),用 API 包装起来。参考代码如下:

public static void main(String[] args) {
    // 初始化配置规则.
    initFlowRules();

    while (true) {
        // 1.5.0 版本开始可以直接利用 try-with-resources 特性
        try (Entry entry = SphU.entry("HelloWorld")) {
            // 被保护的逻辑
            System.out.println("hello world");
	} catch (BlockException ex) {
            // 处理被流控的逻辑
	    System.out.println("blocked!");
	}
    }
}

您也可以通过@SentinelResource 注解,来定义我们的资源,类似于下面的代码:

添加依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>x.y.z</version>
</dependency>

添加配置
若您的应用使用了 Spring AOP,您需要通过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean:

	@Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

注解使用

//blockHandler:流控降级后的处理方法(默认该方法声明在同一个类中)
//fallback:接口出现异常,交给fallback指定的方法进行处理
//blockHandler:使用优先级更高
@SentinelResource(value = "HelloWorld", blockHandler = "exceptionHandler", fallback = "helloFallback" )
public user helloWorld() {
    // 资源中的逻辑
    return new user();
}


    // Fallback 流控降级函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
    public user helloFallback(long s) {
        return new user();
    }

    // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
    public user exceptionHandler(long s, BlockException ex) {
        // Do some log here.
        ex.printStackTrace();
        return new user();
    }

这样,helloWorld() 方法就成了我们的一个资源。

3.定义流控规则

接下来,通过流控规则来指定允许该资源通过的请求次数,例如下面的代码定义了资源 HelloWorld 每秒最多只能通过 20 个请求。

private static void initFlowRules(){
	//创建流控规则
    List<FlowRule> rules = new ArrayList<>();
    //流控
    FlowRule rule = new FlowRule();
    //为哪一个资源流控
    rule.setResource("HelloWorld");
    //设置流控规则 QPS
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    //设置受保护的资源阈值 设置一秒QPS 为 20
    rule.setCount(20);
    rules.add(rule);
    //加载配置好的规则
    FlowRuleManager.loadRules(rules);
}

4.定义熔断降级规则

熔断降级多用在消费方,流量控制多用于生产方

熔断降级规则(DegradeRule)包含下面几个重要的属性:
在这里插入图片描述

    private static void initDegradeRule() {
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule(KEY)
            //设置规则策略
            .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
            // 触发熔断异常数
            .setCount(20)
            // Circuit breaker opens when slow request ratio > 60%
            .setSlowRatioThreshold(0.6)
            //触发熔断最小请求数
            .setMinRequestAmount(50)
            //统计时长(单位毫秒):默认一秒
            .setStatIntervalMs(1000);
            // 熔断时长(秒):10秒内调用该方法走服务降级
            .setTimeWindow(10)
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);
    }

Sentinel 控制台

Sentinel 控制台

注意:启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本

获取 Sentinel 控制台

在这里插入图片描述
下载地址:选择版本、下载jar包文件,其他为源码

本次下载为:sentinel-dashboard-1.8.1.jar

启动

cmd命令启动

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080。
访问端口默认为8080

java -Dserver.port=8088 -jar sentinel-dashboard-1.8.1.jar

点击浏览器访问Sentinel 控制台:8088
在这里插入图片描述
从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel

也可以创建一个批处理文件 sentinel-start.bat 执行启动:

java -Dserver.port=8088 -jar sentinel-dashboard-1.8.1.jar
pause

双击执行

客户端接入控制台

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>x.y.z</version>
</dependency>

后期都不使用这种方式,用一个start就行了

Spring Cloud Alibaba整合sentinel

项目配置

依赖

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                <version>2.2.6.RELEASE</version>
            </dependency>

配置

spring:
  application:
    #nacos 服务注册名称, 远程调用服务使用
    name: order-openfeign
  cloud:
    sentinel:
      transport:
        # 要使用localhost,不然实时监控不显示
        dashboard: localhost:8858

Sentinel 控制台流控配置

在这里插入图片描述

流量控制配置

1. QPS流控

在这里插入图片描述
流量控制的使用场景
在这里插入图片描述
新增QPS规则

在这里插入图片描述
查看
在这里插入图片描述
当对设置规则的接口超量访问时返回:Blocked by Sentinel (flow limiting) - ->> 哨兵阻挡(流量限制)

2.线程数流控

在这里插入图片描述
该接口正在执行接口任务的线程数不能超过指定值

3.服务降级配置

在这里插入图片描述

测试以上配置
    //注入feign远程调用接口
    @Autowired
    private StockFeignService stockFeignService;


    @GetMapping("/add")
    @SentinelResource(value = "add", blockHandler = "addBlockHandler", fallback = "addFallback")
    public Boolean add(Integer num){
        logger.info("进入OrderController.add");
        if (num > 1){
            Integer xx = Integer.valueOf("xx");
        }
        return stockFeignService.add(num);
    }

    public Boolean addBlockHandler(Integer num, BlockException blockException){
        logger.info("blockHandler:流控后的处理方法(默认该方法声明在同一个类中) num:{}, exception:{}", num, blockException.getMessage());
        return false;
    }

    public Boolean addFallback(Integer num){
        logger.info("fallback:服务出错降级后的处理方法 num:{}", num);
        return false;
    }

@SentinelResource :指定自定义服务异常的处理方法

结论:

  • 当服务未发生异常,QPS超过时,服务执行blockHandler方法返回
  • 当服务发生错误时,服务执行fallback,当超过指定异常数时会服务降级,此时访问服务都只会执行blockHandler,直到服务降级时间结束。
  • blockHandler:使用优先级更高
4.关联流控

添加关联资源,用来限制本资源流量

场景:下订单QPS变大时,限制订单查询流量

在这里插入图片描述

5.链路流控

在这里插入图片描述

test1 和 test2方法都要调用getUser方法,
在这里插入图片描述
定义限流资源方法
在这里插入图片描述
block方法注意

  • 此方法不走统 一 BlockException异常
  • 方法为public
  • 返回值类型与限流资源同类型
  • 参数要与限流资源相同且要添加BlockException

控制台配置

在这里插入图片描述

访问没有效果

在这里插入图片描述
解决:在yml文件中添加

在这里插入图片描述
控制台链路显示为

在这里插入图片描述
结果:getUser访问QPS超量,此时访问test2显示被流控,访问test1正常

全局统一流控异常(BlockException)处理

全局统一流控异常返回:当异常为公共的返回时,可以自定义统一处理
实现 BlockExceptionHandler:

@Slf4j
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        // e.getRule() 资源 规则的详细信息
        log.info("自定义全局 BlockExceptionHandler e:{}", e.getRule());

        AjaxResult ajaxResult = null;
        if (e instanceof FlowException){
            //超过QPS流控进入
            ajaxResult = AjaxResult.error(100, "接口限流了");
        }else if (e instanceof DegradeException){
            //异常数到达降级规则执行
            ajaxResult = AjaxResult.error(101, "服务降级了");
        }else if (e instanceof ParamFlowException){
            ajaxResult = AjaxResult.error(102, "热点参数限流了");
        }else if (e instanceof SystemBlockException){
            ajaxResult = AjaxResult.error(103, "触发系统保护规则了");
        }else if (e instanceof AuthorityException){
            ajaxResult = AjaxResult.error(104, "授权规则不通过");
        }
        response.setStatus(200);
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        response.getWriter().print(ajaxResult.toString());
    }
}

新建测试接口,并在控制台设置流控规则

    @GetMapping("/my")
    public AjaxResult myBlockException(Integer num){
        logger.info("测试全局异常");
        if (num > 1){
            Integer xx = Integer.valueOf("xx");
        }
        return success(true);
    }

Sentinel 控制台流控效果

Sentinel 控制台流控效果选项如下图所示:
在这里插入图片描述

快速失败

快速失败是默认的处理方式,当请求达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。

例如我们设置阈值为一秒一个请求,当我们请求QPS超过阈值时候,在浏览器中会直接报错:

Warm Up(预热/冷启动)

阈值一般是一个微服务能承担的最大QPS,但是一个服务刚刚启动时,一切资源尚未初始化(冷启动),如果直接将QPS跑到最大值,可能导致服务瞬间宕机。

warm up也叫预热模式,是应对服务冷启动的一种方案。请求阈值初始值是 maxThreshold / coldFactor,持续指定时长后,逐渐提高到maxThreshold值。而coldFactor的默认值是3.

场景:秒杀机器最大QPS为10,设置阈值maxThreshold为10,预热时间为5秒,那么初始阈值就是 10 / 3 = 3,然后在5秒内逐渐增长到10,防止激增流量。

在这里插入图片描述
案例

需求:给/order/{orderId}这个资源设置限流,最大QPS为10,利用warm up效果,预热时长为5秒。

1)配置流控规则:

在这里插入图片描述

2)Jmeter访问测试

20秒总共访问200次,QPS为10。

在这里插入图片描述

结果:

在这里插入图片描述
结论:

  • 刚刚启动时,大部分请求失败,成功的只有3个,说明QPS被限定在3
  • 随着时间推移,成功比例越来越高,Wamp up效果的阈值是逐渐递增的。
排队等待(脉冲流量)

排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。

  • 当请求超过QPS阈值时,快速失败和warm up 会拒绝新的请求并抛出异常。
  • 目的是让服务以平滑的QPS曲线来消费,不是第一秒100QPS,第二秒1QPS。

案例

需求:给/order/{orderId}这个资源设置限流,最大QPS为10,利用排队的流控效果,超时时长设置为5s

1)添加流控规则

在这里插入图片描述
2)Jmeter测试

在这里插入图片描述

QPS为15,已经超过了我们设定的10。
如果是之前的 快速失败、warmup模式,超出的请求应该会直接报错。

但是我们看看队列模式的运行结果:

在这里插入图片描述

全部都通过了。

再去sentinel查看实时监控的QPS曲线:

在这里插入图片描述

  • QPS非常平滑,一致保持在10,超出的请求会被放入队列,因此请求响应时间会越来越长。
  • 当队列满了以后或超时,才会有部分请求失败。

熔断降级

在分布式架构复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个服务链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。

在这里插入图片描述
熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

熔断策略

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

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

注意异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效

发送熔断后的处理逻辑示例
  • 提供fallback实现服务降级
  • 返回错误result
  • 读缓存(DB访问降级)

openfeign整合sentinel

配置:添加openfeign对 sentinel的支持

feign:
  sentinel:
    enabled: true

配置feign远程调用服务接口

/**
 * 2 配置feign远程调用接口
 * @ FeignClient(name = "Macos服务注册名", path = "/服务提供者控制层入口参数")
 * fallback:服务降级的处理
 */
@FeignClient(name = "stock-service", path = "/stock" , fallback = StockFeignFallbackService.class)
public interface StockFeignService {

    /**
     * 把服务提供者控制层接口直接复制过来, 格式一样
     */
    @GetMapping("/add")
    boolean add(@RequestParam("num") Integer num);

    @GetMapping("/add2")
    String add2(@RequestParam("num") Integer num);
}

服务降级处理

/**
 * openfeign整合sentinel:服务降级处理
 * 流控降级会进入这里
 */
@Component
public class StockFeignFallbackService implements StockFeignService {

    @Override
    public boolean add(Integer num) {
        System.out.println("StockFeignFallbackService.add openfeign整合sentinel实现服务降级处理 ");
        return false;
    }

    @Override
    public String add2(Integer num) {
        System.out.println("StockFeignFallbackService.add2 服务降级处理啦!");
        return "你被服务降级处理啦!";
    }
}

使用

	//注入feign远程调用接口
    @Resource
    private StockFeignService stockFeignService;

	@GetMapping("/add2")
    public AjaxResult add2(Integer num){
        logger.info("测试统一流控和feign整合sentinel服务降级处理");
        return success(stockFeignService.add2(num));
    }

然后就是配置 sentinel控制台,流控及服务降级都会进入StockFeignFallbackService 处理返回

热点参数流控

实现

在这里插入图片描述
控制台配置

在这里插入图片描述

新增后修改 - 高级选项(添加接口参数的热点值)

在这里插入图片描述
运行测试。

系统保护规则

规则持久化

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值