前言
前几天公司生产环境一个服务由于流量上升触发了 Sentinel 的流控机制,然后用户反馈访问慢,定位发现是 task 定时任务导致,后面 task 优化之后发布,流量恢复正常。
这是一个再正常不过的生产问题,可能大部分同学都经历过,经历过的大多数是解决问题之后就不了了之,导致事故还有再次发生的可能,最终对用户造成了不好的体验。所以我觉得所有的生产问题都需要进行复盘,当然复盘的目的不是为了追责,而是防止下次再发生同样的错误。那我们就简单分析一下这个问题,首先肯定是业务层面的疏漏导致 task 发出不合理的大量请求,其二我们的流控只是简单粗暴的流控,没有更好的预警措施,导致影响到用户之后我们才知晓(即流控或熔断已经触发)。
那我们的解决方案呢?首先肯定是业务层面的预防,但这不是本文要说的重点,这里不展开讨论了。其次就是预警,就是我们能否在快要触发流控之前知晓,然后报警到相关负责人提前介入处理,防止触发流控熔断。当然也不能完全避免,但是总比流控或熔断触发之后在报警要好得多。
由于之前流控用的阿里的 Sentinel,所以本文介绍的具体实现是用 Sentinel 的自定义 slot 功能,这个自定义 slot 卡槽在 Sentinel 官方文档里面就一句话带过,然后加上一个 demo 代码,我在使用的过程中也遇到过不少坑,所以分享一下结果给大家。
如果大家对 Sentinel 不是很了解,可以先去 github 先了解简单试用一下在阅读本文。github 地址:https://github.com/alibaba/Sentinel[1]
如果想熟悉自定义 slot 功能建议了解一下 Sentinel 的工作原理:https://github.com/alibaba/Sentinel/wiki/Sentinel%E5%B7%A5%E4%BD%9C%E4%B8%BB%E6%B5%81%E7%A8%8B[2]
还有源码中的 demo 对于自定义 slot 的写法:https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-slot-chain-spi[3]
具体实现
下面介绍下 Sentinel 预警功能的相关实现,使用的前提是你的系统已经在用 Sentinel 的流控或熔断等功能。
自定义 CustomSlotChainBuilder 实现 SlotChainBuilder 接口,这里主要是把我们自定义的 Slot 加到 SlotChain 这个链中
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
import com.alibaba.csp.sentinel.slotchain.SlotChainBuilder;
import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder;
import com.qiaofang.tortoise.gateway.component.ApplicationContextUtil;
import com.qiaofang.tortoise.gateway.config.SentinelProperties;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 自定义slot
*
* @author chenhao
*/
public class CustomSlotChainBuilder implements SlotChainBuilder {
@Override
public ProcessorSlotChain build() {
ProcessorSlotChain chain = new DefaultSlotChainBuilder().build();
SentinelProperties sentinelProperties = (SentinelProperties) ApplicationContextUtil.getContext().getBean("sentinelProperties");
chain.addLast(new FlowEarlyWarningSlot(sentinelProperties));
chain.addLast(new DegradeEarlyWarningSlot(sentinelProperties));
r