SpringCloud入门实战(9)--Sentinel(1)--简介及基本使用

Sentinel是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。本文主要介绍Sentinel的基本使用,文中使用到的软件版本:Sentinel 1.3.2、Spring Boot 2.2.5.RELEASE、Spring Cloud Hoxton.SR3、Java 1.8.0_191。

1、简介

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

1.1、Sentinel特性

1.2、Sentinel组成部分

a、核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
b、控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

2、规则

Sentinel的所有规则都可以在内存中动态地查询及修改,修改之后立即生效。同时Sentinel也提供相关API,供您来定制自己的规则策略。Sentinel支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和热点参数规则。

2.1、流量控制规则(FlowRule)

同一个资源可以同时有多个限流规则,检查规则时会依次检查。其重要属性:

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

编码方式定义规则:

private void initFlowQpsRule() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule(resourceName);
    // set limit qps to 20
    rule.setCount(20);
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setLimitApp("default");
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}

2.2、熔断降级规则(DegradeRule)

同一个资源可以同时有多个降级规则。其重要属性:

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

编码方式定义规则:

private void initDegradeRule() {
    List<DegradeRule> rules = new ArrayList<>();
    DegradeRule rule = new DegradeRule();
    rule.setResource(KEY);
    // set threshold RT, 10 ms
    rule.setCount(10);
    rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
    rule.setTimeWindow(10);
    rules.add(rule);
    DegradeRuleManager.loadRules(rules);
}

2.3、系统保护规则(SystemRule)

Sentinel系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。其重要属性:

Field说明默认值
highestSystemLoad load1 触发值,用于触发自适应控制阶段 -1 (不生效)
avgRt 所有入口流量的平均响应时间 -1 (不生效)
maxThread 入口流量的最大并发数 -1 (不生效)
qps 所有入口资源的 QPS -1 (不生效)
highestCpuUsage 当前系统的 CPU 使用率(0.0-1.0) -1 (不生效)

编码方式定义规则:

private void initSystemRule() {
    List<SystemRule> rules = new ArrayList<>();
    SystemRule rule = new SystemRule();
    rule.setHighestSystemLoad(10);
    rules.add(rule);
    SystemRuleManager.loadRules(rules);
}

2.4、访问控制规则(AuthorityRule)

很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的访问控制(黑白名单)的功能。其重要属性:

resource:资源名,即规则的作用对象
limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式

编码方式定义规则:

AuthorityRule rule = new AuthorityRule();
rule.setResource("test");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
rule.setLimitApp("appA,appB");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));

2.5、热点规则(ParamFlowRule)

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。其重要属性类似于流量控制规则:

属性说明默认值
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 集群流控相关配置  

编码方式定义规则: 

ParamFlowRule rule = new ParamFlowRule(resourceName)
    .setParamIdx(0)
    .setCount(5);
// 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
    .setClassType(int.class.getName())
    .setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));

ParamFlowRuleManager.loadRules(Collections.singletonList(rule));

3、使用

3.1、抛出异常方式使用

SphU包含了try-catch风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。

3.1.1、引入依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.0</version>
</dependency>

3.1.2、样例

package com.abc.demo.test;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

import java.util.ArrayList;
import java.util.List;

public class Sentinel {
    public static void main(String[] args) {
        // 配置规则.
        initFlowRules();
        test();
    }

    private static void test() {
        while(true) {
            // 1.5.0 版本开始可以直接利用 try-with-resources 特性
            Entry entry = null;
            try {
                entry = SphU.entry("HelloWorld");
                // 被保护的逻辑
                System.out.println("hello world");
                //Thread.sleep(1000 * 10);
            } catch (BlockException ex) {
                // 处理被流控的逻辑
                System.out.println("blocked!");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (entry != null) entry.exit();
            }
        }
    }

    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setResource("HelloWorld");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // Set limit QPS to 20.
        rule.setCount(10);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }
}

3.2、结合Spring Cloud使用

3.2.1、引入依赖

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

3.2.2、注解方式使用sentinel

@SentinelResource注解用来标识资源是否被限流、降级。

package com.abc.scdemo.server.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;

@Service
public class SentinelService {
    @SentinelResource(value = "sentinel-test", blockHandler = "blockHandler", fallback = "fallback")
    public String test(long id) {
//        if (true) {
//            throw new RuntimeException("a");
//        }
        return "test";
    }

    /**
     * Block异常处理函数,用来处理Sentinel限流/熔断等错误
     * 参数最后多一个BlockException,其余与原函数一致
     */
    public String blockHandler(long id, BlockException e) {
        e.printStackTrace();
        return "blockHandler";
    }

    /**
     * Fallback函数,用来处理接口中业务代码所有异常
     * 函数签名与原函数一致或加一个 Throwable 类型的参数.
     */
    public String fallback(long id) {
        return "fallback";
    }
}
package com.abc.scdemo.server.controller;

import com.abc.scdemo.server.service.SentinelService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sentinel")
public class SentinelController {
    private Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private SentinelService service;

    @RequestMapping("/test")
    public String test(long id) {
        logger.info(id + "");

        return service.test(id);
    }

    @RequestMapping("/test2")
    public String test2(long id) {
        logger.info(id + "");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test2";
    }
}

一般推荐将@SentinelResource注解加到服务实现上,而在Web层可以在snetinel控制台查看url并定义规则。

3.2.3、sentinel控制台

Sentinel控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。直接使用Spring Cloud Alibaba自带的Web埋点适配。

a、下载控制台的安装包

https://github.com/alibaba/Sentinel/releases

b、启动

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

c、控制台

http://10.49.196.10:8080/   用户名/密码为:sentinel/sentinel

3.2.4、SpingCloud应用中配置Sentinel控制台地址

spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: 10.49.196.10:8080

project:
  name: scdemo-server

启动应用后并访问响应的url,sentinel控制台会出现监控信息:

 可以在对应的url后定义流控规则:

 定义降级规则:

 

posted @ 2020-09-26 14:52  且行且码  阅读(1198)  评论(0编辑  收藏  举报