Sentinel 是阿里巴巴开源的一款服务容错组件,本来打算整理下 Feign 或者 Ribbon 的使用方法,但这两个组件在使用 Spring Cloud 曾经用过,而笔者刚接触 Sentinel 这个微服务组件不久,所以打算记录下 Sentinel 的一些玩法。
Sentinel 主要以流量为切入点,从 流量控制、熔断降级、系统负载保护 等多个维度来帮助用户提升服务的稳定性。说到这熔断,美股几天前刚刚也触发了熔断机制,上者熔断是为了保护业务服务器,而股市中的熔断通过暂停交易防止对市场造成更大的冲击,两者还真有异曲同工之妙哈。Sentinel 的常见的容错方案有下面四种:
java -jar sentinel-dashboard-1.6.3.jar
,这里换成对应 jar 包版本,启动控制台-Dsentinel.dashboard.auth.username=username
-Dsentinel.dashboard.auth.password=password
-Dserver.servlet.session.timeout=7200
如 7200 表示 7200 秒;60m 表示 60 分钟(默认为 30 分钟)Maven 依赖如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
application.yml
加入 sentinel 配置
sentinel:
transport:
dashboard: 127.0.0.1:8080
当依赖和配置添加完毕后,启动自己的微服务业务,然后访问一个端点,由于 Sentinel 的懒加载机制,必须先访问一次微服务业务接口,才能出现左侧配置规则的导航栏,之后尝试添加一个流控规则。
流控规则 QPS 设置为 1,疯狂刷新配置的端点,就会出现被流控的现象,到这一步 Sentinel 也算玩起来了。
高级选型下有三种流控模式:
流控的效果也有三种分别是:快速失败、Warm Up、排队等待
降级规则有下面三种:
-Dcsp.sentinel.statistic.max.rt=xxx
对参数限流,构造一个有两个参数的端点,然后配置一下热点规则
@GetMapping("hot")
@SentinelResource("hot")
public String testHot(@RequestParam(required = false) String a, @RequestParam(required = false) String b) {
return a + " " + b;
}
参数索引是从下标为 0 开始的,则这里配置的 1 表示参数 “b”,当该参数为 “hello” 时,QPS 限制为 1。
系统规则有一下四种:
Sentinel 规则持久化有两种方案,推模式和拉模式,具体配置代码比较多,不贴出来了,不过生产环境下更推荐使用推模式(使用Alibaba Ahas的话略过)。
推模式架构图:
拉模式架构图:
默认 Sentinel 的异常返回是一段小字,提示并不友好,也无法区分到底是限流了还剩降级了,好在官方提供了 UrlBlockHandler 接口,通过实行这个接口就能自定义异常返回了。
/**
* 自定义流控降级等异常处理
*/
@Component
public class MyUrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
ErrorMsg msg = null;
if (e instanceof FlowException) {
msg = ErrorMsg.builder()
.status(100)
.msg("限流了")
.build();
} else if (e instanceof DegradeException) {
msg = ErrorMsg.builder()
.status(102)
.msg("降级了")
.build();
} else if (e instanceof ParamFlowException) {
msg = ErrorMsg.builder()
.status(103)
.msg("热点参数限流")
.build();
} else if (e instanceof SystemBlockException) {
msg = ErrorMsg.builder()
.status(104)
.msg("系统规则,负载..等不满足要求")
.build();
} else if (e instanceof AuthorityException) {
msg = ErrorMsg.builder()
.status(104)
.msg("授权规则不通过")
.build();
}
// HTTP状态码
response.setStatus(500);
response.setCharacterEncoding("utf-8");
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
new ObjectMapper().writeValue(response.getWriter(), msg);
}
}
@Data
@Builder
class ErrorMsg {
private Integer status;
private String msg;
}
Sentinel 的知识点的确很多,这里并没有一一记录,学以致用,就算没用到也要记下来,这样就算以后忘了,还能翻阅回来看看。