微服务架构:基于sentinel的限流、降级、监控

        双11、双12、618秒杀、春晚抢红包等大流量高并发场景,我们再熟悉不过了。在高并发、高可用性后端系统架构设计时,通常要通过限流、降级等措施保障系统的稳定性。在Spring cloud微服务技术选型时,我们可以采用第三方开源架构有Hystrix、Resilience4jSentinel [1]。本文将介绍阿里巴巴Sentinel组件的使用。

       Sentinel 是面向云原生微服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者提升微服务的稳定性,避免系统出现雪崩问题,Sentinel 具有以下特征[2]:

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

       本文将按以下提纲给大家讲解Sentinel限流、降级和监控的实现。

微服务架构:基于sentinel的限流、降级、监控_第1张图片 图1 本文大纲图

1.准备工

1.1 下载sentinel-dashboard.jar

       请到git下载sentinel-dashboard.jar:jar包下载。

图 1.1 下载sentinel-dashboard.jar

1.2. 启动sentinel

在终端输入:

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

 其中: -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080

成功启动sentinel 之后,会在终端输出以下日志信息:

微服务架构:基于sentinel的限流、降级、监控_第2张图片 图 1.2 sentinel启动成功启动截图

2. Sentinel限流、降级(静态配置)

       Sentinel提供丰富的功能,请见本文第5小节的内容介绍。在本节中,博主将介绍限流、降级的使用。其用法挺简单的,定义好了配置资源,使用即可。定义配置资源,有两种方式:抛出异常的方式定义资源、通过注解定义资源。由于注解定义资源更加灵活、使用更加方便,所以本节介绍注解方式的实现,只需要四步操作即可。

2.1引入sentinel注解依赖

implementation "com.alibaba.csp:sentinel-annotation-aspectj:${sentinel_version}"

2.2 定义SentinelAspectConfiguration

package com.rzl.spring.sentinel.configuration;


import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

2.3 定义规则类

     2.3.1 定义规则类为Component,自动初始化规则,不需要手动执行规则初始化。

// 定义为Component,自动初始化规则
@Component
public class StaticRuleser {
    // 资源key
    public static final String RESOURCE_LOGIN = "login"; // 登录
    public static final String RESOURCE_LOGOUT = "logout"; // 登出

    @Bean
    @PostConstruct // 注解不可少
    public static void initFlowQpsRule() {
        List rules = new ArrayList();

        // login ruls
        FlowRule flowRule = new FlowRule();
        setLimitFlowRule(rules, flowRule, RESOURCE_LOGIN);

        // logout ruls
        flowRule = new FlowRule();
        setLimitFlowRule(rules, flowRule, RESOURCE_LOGOUT);

        FlowRuleManager.loadRules(rules);

    }

    @Bean
    @PostConstruct // 注解不可少
    public static void initDegrateRule() {
        List rules = new ArrayList();

        // login ruls
        DegradeRule degradeRule = new DegradeRule();
        setDegradeRule(rules, degradeRule, RESOURCE_LOGIN);

        // logout ruls
        degradeRule = new DegradeRule();
        setDegradeRule(rules, degradeRule, RESOURCE_LOGOUT);

        DegradeRuleManager.loadRules(rules);
    }

    ......
}

  2.3.2 根据需要,设置限流规则、降级规则。它们的规则通常如下:

1)限流规则

    @PostConstruct // 注解不可少
    public static void initFlowQpsRule() {
        List rules = new ArrayList();

        // login ruls
        FlowRule flowRule = new FlowRule();
        setLimitFlowRule(rules, flowRule, RESOURCE_LOGIN);

        // logout ruls
        flowRule = new FlowRule();
        setLimitFlowRule(rules, flowRule, RESOURCE_LOGOUT);

        FlowRuleManager.loadRules(rules);
    }

setLimitFlowRule的具体规则设置如下:

     /**
     * 初始限流rule配置
     * {
     *         "resource":"your resource name",
     *         "limitAPP":"default",
     *         "grade":1,
     *         "count":20,
     *         "clusterMode":false
     *         "strategy":0,
     *         "controlBehavior":0,
     *  }
     */
    private static void setLimitFlowRule(List rules, FlowRule flowRule, String resourceLogout) {
        flowRule.setResource(resourceLogout); // 资源名
        flowRule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT); // 针对来源,默认
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 阈值类型,QPS限流
        flowRule.setCount(2); // 单机阈值,QPS控制在2以内
        flowRule.setClusterMode(false); // 是否是集群
        flowRule.setStrategy(RuleConstant.STRATEGY_DIRECT); // 流控模式
        flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); // 流控效果
        rules.add(flowRule);
    }

       每个字段是什么意思,读者可以查看API说明。为了让大家对每个字段有一个直观的理解,博主把Sentinel dashboard后台限流规则配置界面贴出来,它们基本是一一对应的。

微服务架构:基于sentinel的限流、降级、监控_第3张图片 图 2.1 限流规则面版

2)降级规则

    @PostConstruct // 注解不可少
    public static void initDegrateRule() {
        List rules = new ArrayList();

        // login ruls
        DegradeRule degradeRule = new DegradeRule();
        setDegradeRule(rules, degradeRule, RESOURCE_LOGIN);

        // logout ruls
        degradeRule = new DegradeRule();
        setDegradeRule(rules, degradeRule, RESOURCE_LOGOUT);

        DegradeRuleManager.loadRules(rules);
    }

setDegradeRule的具体规则设置如下:

    /**
     * 初始降级rule配置
     * {
     *         "resource":"your resource name",
     *         "grade":1,
     *         "count":20,
     *         "slowRatioThreshold":0.5
     *         "timeWindow":1000,
     *         "minRequestAmount ":5,
     *         "statIntervalMs": 1000
     *  }
     */
    private static void setDegradeRule(List rules, DegradeRule degradeRule, String resourceLogin) {
        degradeRule.setResource(resourceLogin); // 资源名
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT); // 熔断策略
        degradeRule.setCount(2); // 域值,最大RT
        degradeRule.setSlowRatioThreshold(0.5);  // 比例阈值
        degradeRule.setTimeWindow(10); // 熔断时长
        degradeRule.setMinRequestAmount(5); // 最小请求数
        degradeRule.setStatIntervalMs(1000); // 统计时长
        rules.add(degradeRule);
    }

     Sentinel dashboard后台降级规则配置界面如下图所示,它们是一一对应的。

微服务架构:基于sentinel的限流、降级、监控_第4张图片 图2.2 熔断规则界面

2.4 规则使用

2.4.1 引入逐渐关键字:SentinelResource。SentinelResource需要设置四个常数如下(也可以为空):

value             : 资源的key
blockHandlerClass : 限流异常处理类
blockHandler      : 限流异常处理方法
fallbackClass     : 熔断处理类
fallback          : 熔断处理方法

例如:login、logout方法设置限流和熔断规则。

    @SentinelResource(value = StaticRuleser.RESOURCE_LOGIN,
            blockHandlerClass = LimitRuleBlockHandler.class,
            blockHandler = "blockHandlerLimitError",
            fallbackClass = DegrateRuleBlockHandler.class,
            fallback = "handlerDegrateError")
    public String login(String userName, String psw) {
        // 测试降级的代码
        if (psw.equals("123456")) {
            throw new RuntimeException();
        }
        return "login successful";
    }

    @SentinelResource(value = StaticRuleser.RESOURCE_LOGOUT,
            blockHandlerClass = LimitRuleBlockHandler.class,
            blockHandler = "blockHandlerLimitError",
            fallbackClass = DegrateRuleBlockHandler.class,
            fallback = "handlerDegrateError")
    public String logout() {
        return "logout successful";
    }
}

2.4.2 限流和熔断处理类的实现

 1)限流处理类:根据login、logout的API,博主定义对应的限流处理方法。细心的小伙伴发现里面这2个方法参数不一样。第一个方法有三个参数,而第二方法只有一个参数。它们分别对应login、logout的异常处理,参数和login、logout传参保持一致。限流处理类接收BlockException异常。

public class LimitRuleBlockHandler {
    public static String blockHandlerLimitError(String userName, String psw, BlockException e) {
        return "流量过大,开始限流,请等候。";
    }

    public static String blockHandlerLimitError(BlockException e) {
        return "流量过大,开始限流,请等候。";
    }
}

2)降级处理类:根据login、logout的API,博主定义对应的降级处理方法。它也有2个方法,参数不一样。第一个方法有三个参数,第二方式只有一个参数。它们分别对应login、logout的异常处理,参数和login、logout传参保持一致。降级处理类接收Throwable异常。

public class DegrateRuleBlockHandler {
    public static String handlerDegrateError(String userName, String psw, Throwable e) {
        return "服务异常,降级处理,请等候。";
    }

    public static String handlerDegrateError(Throwable e) {
        return "服务异常,降级处理,请等候。";
    }

}

2.5 限流、降级测试

 启动服务器,在浏览器输入:http://localhost:8081/sentinel-static-rule/login?userName=rzl&password=123,

1) 在QPS控制以内正常刷新页面输出正常结果:“login successful

2)狂刷页面会报异常:“流量过大,开始限流,请等候”,过一会刷新页面又正常了,说明限流起作用了。

3)测试熔断:在浏览器地址修改密码为123456, 抛出一个异常,界面输出:“服务异常,降级处理,请等候”。

注意如果修改过异常处理类的名字、参数的,记得rebuild project,因为使用了注解,rebuild project才会更新对应的代码。否则,会找不到对应的限流、降低处理方法。

3. Sentinel限流、降级(动态配置)

    上面介绍了静态配置限流、降级规则,但很多时候需要不断增加或修改规则,那么就必须采用动态配置的方法了。Sentinel dashboard后台其实支持可在线配置对应的规则,如下图所示:

微服务架构:基于sentinel的限流、降级、监控_第5张图片 图3.1 sentinel dashboard配置规则后台

      但是每次我们重启Sentinel之后,配置的规都会全部丢失。所以, 我们需要解决如何保存配置规则的问题。前面我们已经介绍过nacos配置中心,我们可以将规则保存到nacos配置中心,解决这个问题。由于篇幅受限的原因,博主将在下一篇博客介绍如何将Sentinel配置规则推送Nacos配置中心进行储存。

4. Sentinel 监控

       Sentinel dashboard是一个轻量级界面后台,可以非常直观监控接口、机器、集群运行的情况,同时支持在线新增、修改限流、降级等规则。下面来介绍Sentinel dashboard监控功能使用。

4.1 引入控制台通信依赖

implementation "com.alibaba.csp:sentinel-transport-simple-http:${sentinel_version}"

4.2  JVM 启动参数

-Dproject.name=sentinel-demo -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 -Dcsp.sentinel.api.port=8719

微服务架构:基于sentinel的限流、降级、监控_第6张图片 图4.1 JVM 启动参数

4.3 Sentinel监控台使用

    重启Sentinel之后,在浏览器打开:http://localhost:8080/,随即进入sentinel的登录界面,输入账号和密码:

账号:sentinel

密码:sentinel

微服务架构:基于sentinel的限流、降级、监控_第7张图片 图4.2 Sentinel登录界面

      登录成功之后,会进入sentinel dashboard的首页,发现我们的项目已经在左边侧边栏显示出来了。sentinel提供了丰富的功能,如实时监控、簇点链路、降级规则、熔断规则、热点规则、系统规则、授权规则、集群流控、机器列表。用户可以简单、直观地编辑规则,监控API、机器列表、集群的情况。

  1)实时监控

微服务架构:基于sentinel的限流、降级、监控_第8张图片 图4.3 实时监控图

  2)簇点链路

微服务架构:基于sentinel的限流、降级、监控_第9张图片 图4.4 簇点链路图

 3)降级规则

微服务架构:基于sentinel的限流、降级、监控_第10张图片 图4.5 降级规则图

 4)熔断规则

微服务架构:基于sentinel的限流、降级、监控_第11张图片 图4.6 熔断规则图

  5)热点规则

微服务架构:基于sentinel的限流、降级、监控_第12张图片 图4.6 热点规则图

 6)系统规则

微服务架构:基于sentinel的限流、降级、监控_第13张图片 图4.7 系统规则图

 7)授权规则

微服务架构:基于sentinel的限流、降级、监控_第14张图片 图4.8 授权规则图

8)集群流控

微服务架构:基于sentinel的限流、降级、监控_第15张图片 图4.9 集群流控

9)机器列表

微服务架构:基于sentinel的限流、降级、监控_第16张图片 图4.10 机器列表

5.Demo代码

   demo代码已经上传git,需要的读者请自行下载,代码下载地址。

6.参考链接

1)限流熔断技术选型:从Hystrix到Sentinel

2)Sentinel: 分布式系统的流量防卫兵

你可能感兴趣的:(后端)