背景

近期收到线上报警,发现个别新接口在同1s内被请求了接近上百次,对系统的稳定造成了一些影响,近期调研了一下通用的限流框架,打算将Sentinel的限流功能集成进新服务

Sentinel前置知识

Sentinel 限流主要涉及以下几方面

Resource

限流的资源,资源支持动态加载,核心类为: AbstractDataSource ,Sentinel 默认提供了市面常见的资源管理服务的实现,也可以自定义实现

Rule

对定义的 Resouce 应用的限流规则,基于QPS、响应时间与系统负载。Sentinel 是通过一系列的功能Slot来实现不同的统计/控制功能,对于限流功能对应的就是 FlowSlot

FlowSlot 的功能实现需要依赖前面的 NodeSelectorSlotClusterBuilderSlot 等统计Slot,有了统计信息才可以针对配置进行限流操作,这里面借用一张官方的实现图

各Slot默认的顺序也可以在代码中找到

核心处理逻辑

核心逻辑是在执行调用chain的捕获Blockexcption然后执行后续操作

集成步骤

借助SpringMVC中提供的 HandlerInterceptor 拦截器功能 与 Sentinel 提供的SpringMVC框架集成类库可以方便快速的实现限流功能

引入Sentinel SpringMVC Adapter

1
2
3
4
5
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-webmvc-adapter</artifactId>
    <version>1.8.8</version>
</dependency>

配置SentinelWebInterceptor

Sentinel SpringMVC Adapter中提供了 SentinelWebInterceptor 来实现限流功能,这个 Interceptor 支持一些自定义的行为,主要通过 SentinelWebMvcConfig 来实现

SentinelWebMvcConfig 常用配置说明

SentinelWebMvcConfig 支持以下配置能力

  • urlCleaner

    自定义对请求url的处理,比如厂商此次需要通过请求的设备id维度进行限流,对于其它的请求参数都进行忽略,最终可定义效果为: /api/v1/test/ping?did=6308103f1026acf274bbcc1b10001291551xxX

  • httpMethodSpecify

    是否指定特定的Http请求方法,此设置是对资源的请求方法进行了细粒度的配置,默认为false不开启,配置为true后,会在设定好的资源名前加上请求的方法,类似效果: GET: /api/v1/test/ping?did=6308103f1026acf274bbcc1b10001291551xxX

  • blockExceptionHandler

    被Block的请求异常处理器,对Block的请求进行自定义处理,可以设置返回的值,如果未配置则需要服务自己捕获 BlockException,可以通过配置 ExceptionHandler 进行统一处理

  • originParser

    请求来源处理器,针对请求的来源进行处理,在配置资源的规则的可以使用此解析的origin细粒度控制,例如可以解析ip、用户做为请求 origin

配置 SentinelWebMvcConfig

由于此次只需要根据用户设备维度进行限流,所以只自定义配置了 urlCleaner,代码如下:

对于BlockException统一配置ExceptionHandler实现

新增 DefaultSentinelInterceptor

为了后续能将此功能做的更通用,没有直接使用 SentinelWebInterceptor , 而是新增了 SentinelWebInterceptor 一个子类 DefaultSentinelInterceptor ,将 DefaultSentinelInterceptor 做为Spring的一个Component进行管理,这样就可以方便的把上述配置的 SentinelWebMvcConfig 进行注入

配置 DefaultSentinelInterceptor 到 Spring的WebMvcConfigurer中

在 WebMvcConfigurer 的实现类增加 DefaultSentinelInterceptor 拦截器配置,配置其优先级为 PrepareInterceptor 后

配置的资源在哪?

找了一下,Peacock已经提供了基于七彩石配置的Resouce实现 RainbowSentinelDatasourceInit ,配置在 SentinelDatasourceConfiguration ,解析的是 flowRule.json 文件,配置的内容就是官方的配置风格,这样看完全可以拿来一用而不需要再实现一遍了。

来看看 flowRule.json 能配置哪些内容

再借一张官方图

基本上使用了官方提供的默认配置值即可,对于 count 值可以根据线上提供服务的机器数进行配置即可。在实现配置时增加了一个 regex 项,即支持正则匹配,这样对于厂商根据设备id的维度进行限流就可以在 resource 项直接配置一个正则就可以了,具体配置如下:

  1. strategy可配置值为 0(直接)、1(链路)、2(关联)
  2. controlBehavior可配置值为 0. 直接拒绝, 1. WarmUp, 2. 匀速, 3. 排队等待

REF

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