双11、双12、618秒杀、春晚抢红包等大流量高并发场景,我们再熟悉不过了。在高并发、高可用性后端系统架构设计时,通常要通过限流、降级等措施保障系统的稳定性。在Spring cloud微服务技术选型时,我们可以采用第三方开源架构有Hystrix、Resilience4j、Sentinel [1]。本文将介绍阿里巴巴Sentinel组件的使用。
Sentinel 是面向云原生微服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者提升微服务的稳定性,避免系统出现雪崩问题,Sentinel 具有以下特征[2]:
本文将按以下提纲给大家讲解Sentinel限流、降级和监控的实现。
图1 本文大纲图1.1 下载sentinel-dashboard.jar
请到git下载sentinel-dashboard.jar:jar包下载。
图 1.1 下载sentinel-dashboard.jar1.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 之后,会在终端输出以下日志信息:
图 1.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后台限流规则配置界面贴出来,它们基本是一一对应的。
图 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后台降级规则配置界面如下图所示,它们是一一对应的。
图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才会更新对应的代码。否则,会找不到对应的限流、降低处理方法。
上面介绍了静态配置限流、降级规则,但很多时候需要不断增加或修改规则,那么就必须采用动态配置的方法了。Sentinel dashboard后台其实支持可在线配置对应的规则,如下图所示:
图3.1 sentinel dashboard配置规则后台但是每次我们重启Sentinel之后,配置的规都会全部丢失。所以, 我们需要解决如何保存配置规则的问题。前面我们已经介绍过nacos配置中心,我们可以将规则保存到nacos配置中心,解决这个问题。由于篇幅受限的原因,博主将在下一篇博客介绍如何将Sentinel配置规则推送Nacos配置中心进行储存。
Sentinel dashboard是一个轻量级界面后台,可以非常直观监控接口、机器、集群运行的情况,同时支持在线新增、修改限流、降级等规则。下面来介绍Sentinel dashboard监控功能使用。
4.1 引入控制台通信依赖
implementation "com.alibaba.csp:sentinel-transport-simple-http:${sentinel_version}"
4.2 JVM 启动参数
图4.1 JVM 启动参数
-Dproject.name=sentinel-demo -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 -Dcsp.sentinel.api.port=8719
4.3 Sentinel监控台使用
重启Sentinel之后,在浏览器打开:http://localhost:8080/,随即进入sentinel的登录界面,输入账号和密码:
图4.2 Sentinel登录界面账号:sentinel
密码:sentinel
登录成功之后,会进入sentinel dashboard的首页,发现我们的项目已经在左边侧边栏显示出来了。sentinel提供了丰富的功能,如实时监控、簇点链路、降级规则、熔断规则、热点规则、系统规则、授权规则、集群流控、机器列表。用户可以简单、直观地编辑规则,监控API、机器列表、集群的情况。
1)实时监控
图4.3 实时监控图2)簇点链路
图4.4 簇点链路图3)降级规则
图4.5 降级规则图4)熔断规则
图4.6 熔断规则图5)热点规则
图4.6 热点规则图6)系统规则
图4.7 系统规则图7)授权规则
图4.8 授权规则图8)集群流控
图4.9 集群流控9)机器列表
图4.10 机器列表demo代码已经上传git,需要的读者请自行下载,代码下载地址。
1)限流熔断技术选型:从Hystrix到Sentinel
2)Sentinel: 分布式系统的流量防卫兵