Sentinel 流控规则详解(上)

简介: Sentinel 流控规则详解

在前面两篇文章给大家介绍了 Sentinel 的功能和基本使用。现在我们继续来学习 Sentinel 控制台的基本使用,以及一些规则配置的说明。让大家能够在工作中使用 Sentinel 得心应手 (大部分理论和描述来源于官方文档和网络)。


在正文开始之前,我先说一下我的基本环境信息


  • jdk 1.8
  • sentinel 1.8.0
  • spring-boot 2.3.5.RELEASE
  • spring-cloud Hoxton.SR8
  • spring-cloud-alibaba 2.2.5.RELEASE


控制台简介


Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。这里,我们将会详细讲述如何通过简单的步骤就可以使用这些功能。


Sentinel 控制台包含如下功能:


  • 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
  • 监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
  • 规则管理和推送:统一管理推送规则。
  • 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。


注意:Sentinel 控制台目前仅支持单机部署。Sentinel 控制台项目提供 Sentinel 功能全集示例,不作为开箱即用的生产环境控制台,若希望在生产环境使用需要自行定制和改造


Alibaba 提供了企业版本的 Sentinel 我们可以在 aliyun.com 上面购买 AHAS Sentinel


查看机器列表以及健康情况


如果我们正确的接入 Sentinel 之后我们可以在 Sentinel 控制台的 机器列表 菜单中来查看我们服务节点的健康情况


sentinel 机器列表查看健康状态.png

stock-service

机器列表实例总数2,健康1,失联1.

关键字

健康状态

IP地址

Sentinel客户端版本

操作

心跳时间

端口号

机器名

2021/05/1614:07:51

172.20.10.3

健康

1.8.0

8721

54c787867b71.local

1.8.0

8722

2021/05/1614:05:04

172.20.10.3

失联

54c787867b71.local

移除

共2条记录,每页

条记录,第1/1页

10


如果 Sentinel 接入不成功,可以查阅 Sentinel 官方文档或者 FAQ 来对应排查


服务监控


1. 实时监控


同时,同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在"实时监控"下。


注意: 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。


sentinel 实时监控只存5分钟.png

order-service

实时监控

升序

关键字

Lerror

响应时间(ms)

通过QPS

时间

拒绝QPS

0.8

3.0

14:14:57

1.0

0.0

0.6

5.0

14:14:54

1.0

0.0

0.4

14:14:51

0.0

5.0

1.0

0.2

14:14

14:14

14:14

14:14

14:14

14:14

通过QPS-拒绝QPS


注意:请确保 Sentinel 控制台所在的机器时间与自己应用的机器时间保持一致,否则会导致拉不到实时的监控数据。


2. 簇点链路


簇点链路(单机调用链路)页面实时的去拉取指定客户端资源的运行情况。它一共提供两种展示模式:一种用树状结构展示资源的调用链路,另外一种则不区分调用链路展示资源的实时情况。


注意: 簇点链路监控是内存态的信息,它仅展示启动后调用过的资源。


sentinel 簇点链路.png

列表视图

树状视图

order-service

康点链路

刷新

关键字

172.20.10.3:8720

通过QPS

资源名

分钟拒绝

操作

拒绝QPS

线程数

平均RT

分钟通过

0

0

0

0

0

sentineldefault.context

降级

+授权

热点

流控

0

0

0

0

sentinelspring_web.context

授权

降级

热点

流控

0

0

0

0

0

授权

流控

降级

热点

o

0

0

0

0

0

/error

流控

授权

降级

热点

0

0

0

0

0

0

hello

+降级

授权

流控

热点

0

0

0

0

0

/hello1

降级

授权

热点

流控

0

0

0

GEThttp://stock-service/getStocDetall

0

授权

降级

热点

流控

0

0

0

0

0

0

hello2

授权

流控

降级

热点

o

0

0

0

0

0

GEThttp://stock-service

流控

热点

授权

降级

条记录

共9条记录,每页

16


注意:请确保 Sentinel 控制台所在的机器时间与自己应用的机器时间保持一致,否则会导致拉不到实时的监控数据。


3 流控规则


流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。


FlowSlot 会根据预设的规则,结合 NodeSelectorSlotClusterBuilderSlotStatisticSlot 统计出来的实时信息进行流量控制。


sentinel 控制台增加流控规则2.png

新增流控规则

资源名

lgetStockDetail

针对来源

default

单机阁值

闹值类型

单机阁值

线程数

QPS

是否集群

流控模式

关联

直接

链路

流控效果

快速失败

排队等待

WarmUp

关闭高级选项

新增

新增并继续添加

取消


限流的直接表现是在执行 Entry nodeA = SphU.entry(resourceName) 的时候抛出 FlowException 异常。FlowExceptionBlockException 的子类,您可以捕捉 BlockException 来自定义被限流之后的处理逻辑。


Sentinel 在触发规则保护时,返回的异常页面是一样的。不好区分是因为哪种规则导致的异常。所以需要自定义异常返回信息,明确是触发了哪种类型的规则。


@Component
public class SentinelBlockHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                       BlockException e) throws Exception {
        CommonResult<Void> result = new CommonResult<>();
        if (e instanceof FlowException) {
            result = CommonResult.error(101, "接口限流了");
        } else if (e instanceof DegradeException) {
            result = CommonResult.error(102, "服务降级了");
        } else if (e instanceof ParamFlowException) {
            result = CommonResult.error(103, "热点参数限流了");
        } else if (e instanceof SystemBlockException) {
            result = CommonResult.error(104, "系统规则(负载/...不满足要求)");
        } else if (e instanceof AuthorityException) {
            result = CommonResult.error(105, "授权规则不通过");
        }
        // http状态码
        httpServletResponse.setStatus(500);
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setHeader("Content-Type", "application/json;charset=utf-8");
        httpServletResponse.setContentType("application/json;charset=utf-8");
        // spring mvc自带的json操作工具,叫jackson
        new ObjectMapper().writeValue(httpServletResponse.getWriter(), result);
    }
}


效果如下:


➜ curl http://127.0.0.1:8088/getStockDetail
{"code":1,"message":"this is a success message","data":{"id":1,"code":"STOCK==>1000"}}%                                                       ➜ curl http://127.0.0.1:8088/getStockDetail
{"code":1,"message":"this is a success message","data":{"id":1,"code":"STOCK==>1000"}}%                                                        ➜ curl http://127.0.0.1:8088/getStockDetail
{"code":101,"message":"接口限流了","data":null}%

阈值类型


线程数


并发数控制用于保护业务线程池不被慢调用耗尽。例如,当应用所依赖的下游应用由于某种原因导致服务不稳定、响应延迟增加,对于调用者来说,意味着吞吐量下降和更多的线程数占用,极端情况下甚至导致线程池耗尽。为应对太多线程占用的情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢(线程池隔离)。这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置。


sentinel 控制台-流控规则线程数.png

新增流控规则

资源名

IgetStockDetail

default

针对来源

阅值类型

单机闽值

5

线程数

OQPS

是否集群

流控模式

O关联

链路

直接

关闭高级选项

新增并继续添加

新增

取消


可以通过线程池模拟客户端调用, 也可以通过  Jmeter 模拟,触发流控的结果如下:


➜  ~ curl http://127.0.0.1:8088/getStockDetail
{"code":101,"message":"接口限流了","data":null}%

流控模式


调用关系包括调用方、被调用方;一个方法又可能会调用其它方法,形成一个调用链路的层次关系。


直接


当资源触发流控规则过后直接,抛出异常信息


➜  ~ curl http://127.0.0.1:8088/getStockDetail
{"code":101,"message":"接口限流了","data":null}%

关联


当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写的速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说,read_dbwrite_db 这两个资源分别代表数据库读写,我们可以给 read_db 设置限流规则来达到写优先的目的:设置 strategyRuleConstant.STRATEGY_RELATE 同时设置 refResourcewrite_db。这样当写库操作过于频繁时,读数据的请求会被限流。


sentinel 控制台-流控规则关联.png

新增流控规则

资源名

lgetStockDetail

default

针对来源

阅值类型

单机间值

QPS

线程数

当前资源

如果关联资源到达回值,

是否集群

触发流控

流控模式

直接

关联

链路

关联资源

/hello

流控效果

快速失败

排队等待

WarmUp

关闭高级选项

新增

取消

新增并继续添加


如果配置流控规则为关联模式,那么当 /hello 接口超过阈值过后,就会对 /getStockDetail 接口触发流控规则。


链路


NodeSelectorSlot 中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root 的虚拟节点,调用链的入口都是这个虚节点的子节点。


一棵典型的调用树如下图所示:


                 machine-root
                   /       \
                  /         \
            Entrance1     Entrance2
               /             \
              /               \
     DefaultNode(nodeA)   DefaultNode(nodeA)


上图中来自入口 Entrance1Entrance2 的请求都调用到了资源 NodeA,Sentinel 允许只根据某个入口的统计信息对资源限流。比如我们可以设置 strategyRuleConstant.STRATEGY_CHAIN,同时设置 refResourceEntrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而不关心经 Entrance2 到来的调用。


调用链的入口(上下文)是通过 API 方法 ContextUtil.enter(contextName) 定义的,其中 contextName 即对应调用链路入口名称。详情可以参考 ContextUtil 文档。]


sentinel 控制台-流控规则链路.png

新增流控规则

GET:http://stock-service/getStockDetail

资源名

针对来源

default

单机阁值

阅值类型

线程数

QPS

如果存在多个资源调用当前资源GET:XXX

是否集群

只有当/gntStockDetail

etail调用触发回值才流控

流控模式

?关联

直接

链路

入口资源

lgetStockDetail

流控效果

快速失败OWarmUp

排队等待

关闭高级选项

新增并继续添加

取消

新增


测试会发现 链路 不会生效


从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效。1.7.0版本开始(对应SCA 2.1.1.RELEASE),我们在CommonFilter引入了WEB_CONTEXT_UNIFY这个init parameter,用于控制是否收敛context。将其配置为false即可根据不同的URL进行链路限流。参考:https://github.com/alibaba/sentinel/issues/1213


解决方案:


1.7.0 版本开始(对应Spring Cloud Alibaba的2.1.1.RELEASE) 需要新增依赖


@Configuration
public class FilterContextConfig {
    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        // 入口资源关闭聚合
        registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
        registration.setName("sentinelFilter");
        registration.setOrder(1);
        return registration;
    }
}

然后我们再尝试触发流控规则, 对 /getStockDetail 进行访问,这里返回了FlowException


sentinel 控制台-流控规则控制台报错.png

544---[nio-8066-exec-9]c.s.o

2021-05-1616:10:42.408ERROR18544

com.alibaba.cspentinkowEcetionn

[nio-8066-exec-ijc.so

2021-05-1616:10:42.686ERROR18544

com.alibaba.csp.entinwwxcetionu

[nio-8066-exec-2]c.s.of

2021-05-1616:10:42.767ERROR18544

com.atibabacpic

2021-0-1616:10:429

com.atibabacpici


默认情况会返回


sentinel 控制台-流控关联-500.png

127.0.0.1

WhitelabelErrorPage

Thisapplicarionhasnocxplicitmpingo/eoinghilck

SunMay1616:23:30CST2021

Therewasanunexpectederror(type-InternalServerError,status-5.


如果我们使用 OpenFeign 不添加 fallbackFactory 就会返回500 , 如果我们添加了就可以避免这个问题。


// Controller
@Autowired
private StockFeign stockFeign;
@GetMapping("/getStockDetail")
public CommonResult<StockModel> getStockDetail() {
  CommonResult<StockModel> result = stockFeign.getStockDetail();
  if (result.getCode() != 1) {
    return CommonResult.error(null, result.getCode(), result.getMessage());
  }
  return result;
}
// FeignClient
@FeignClient(name = "stock-service")
        //, fallbackFactory = StockFeignFallbackFactory.class)
public interface StockFeign {
    @GetMapping("/getStockDetail")
    CommonResult<StockModel> getStockDetail();
}


Sentinel 部分源码:


sentinel 控制台-流控源码 1.png

SentinellnvocationHandler.java

TesutMtHOAN

107

108

catch(Throwableex)

"ComALibabacP

109

ex:

/faiibackhandle

110

i(!BLockException.iBLockException(ex))

111

ex:"com.aLibaba.cpeninckowFowExce

Tracer.trace(ex);

112

113

if

(faltbackFactory

114

alibackFactory:

nutt

nul1)

115

objectfaltbackResult

116

faLtbackMethodMap.ge(meho)

invoke(faitbackFactory.crete(ex),

117

118

returnfaltbackResutt;

119

catch(ILLegalaccessExceptione)

120

121

happenasmethodispublicduetobeinga

mshouldnth

/interface

122

thrownewassertionerror(e);

123

124

catch(InvocationTargetExceptione)

125

thrownewassertionerror(e.getcause)

126

127

P

128

else

129


所以,我们在设置链路流控规则的时候一定要设置 fallbackFactory。不然无法处理 FlowExecption 异常信息,造成系统出错。对于个人而言,Sentinel 的链路规则比不是特别的好用,无特殊要求,不建议使用,或者选择Sentinel 的收费版本 AHAS


相关文章
|
2月前
|
监控 API 开发者
Sentinel之道:流控模式解析与深度探讨
Sentinel之道:流控模式解析与深度探讨
54 0
|
4月前
|
监控 Java 数据安全/隐私保护
Sentinel黑白名单授权规则解读
Sentinel黑白名单授权规则解读
|
4月前
|
监控 Java Nacos
【分布式流控组件 Sentinel 快速入门】——图文详解操作流程(上)
【分布式流控组件 Sentinel 快速入门】——图文详解操作流程
137 0
【分布式流控组件 Sentinel 快速入门】——图文详解操作流程(上)
|
2月前
|
监控 数据挖掘 索引
深度剖析Sentinel热点规则
深度剖析Sentinel热点规则
79 1
|
2月前
|
监控 Java API
解密Sentinel中流控规则的阀值奥秘
解密Sentinel中流控规则的阀值奥秘
18 0
解密Sentinel中流控规则的阀值奥秘
|
2月前
|
监控 Java API
数字护盾:深度探讨Sentinel的三大流控策略
数字护盾:深度探讨Sentinel的三大流控策略
19 0
|
3月前
|
监控 测试技术 数据安全/隐私保护
如何集成Sentinel实现流控、降级、热点规则、授权规则总结
如何集成Sentinel实现流控、降级、热点规则、授权规则总结
78 0
|
4月前
|
Sentinel
一文速通Sentinel熔断及降级规则
一文速通Sentinel熔断及降级规则
|
4月前
|
消息中间件 Java API
一文带你速通Sentinel限流规则(流控)解读
一文带你速通Sentinel限流规则(流控)解读
|
4月前
|
监控 Dubbo Linux
【分布式流控组件 Sentinel 快速入门】——图文详解操作流程(下)
【分布式流控组件 Sentinel 快速入门】——图文详解操作流程(下)
104 0