本文概览:介绍了Sentinel Client和Sentinel Dashboard通信流程,以及 Sentinel执行一次指标收集和规则校验流程(通过责任链slotChain来完成)。

1 RPC

1

1.1  客户端

1.1.1  Sentinel Client的RPC Server

SimplehttpCommandCenter启动了一个客户端服务

1、初始化

获取实现CommandlHandler和使用@CommandMapping的所有对象。

2、启动Server socket,使用BIO模式

查看HttpEventTask的执行逻辑:

1.1.2   Sentinel Dashboard 的RPC Client

定义了一个SimpleHttpClient。下面代码每次都是新建一个socket,由于只是给客户端发送心跳使用,所以没有性能要求。

1.2 Sentinel Dashboard

1.2.1 Sentinel Dashboard 的RPC Server

直接使用dashboard服务作为一个http server

1.2.2 Sentinel Client 的RPC Client

sentinel 客户端相关操作封装在了SentinelAPiClient,SentinelAPiClient通过一个apache的HttpClient来请求Sentinel Client的RP Server

 

2  Sentinel Client 和Sentinel Dashboard通信

2.1 服务注册中心

客户端给服务端发送心跳,频率是5s

客户端直接通过httpClient调用Sentinel Dashboard的/registry/machine,来发送心跳信息

1

2.2 SentinelDashboard获取实例指标数据

STEP1 sentinel dashboard通过http client访问客户端实例的接口  http://xxxx:xx/metric?startTime=1596176146000&endTime=1596176152000&refetch=false

STEP2 sentinel客户端提供了一个RPC服务,反序列化字节流为http request。执行如下:

通过读取指标文件获取指标信息:

2.3 Sentinel Dashboard获取簇节点链路

1、 dashboard提供了/resource/machineResource.json?ip=xxx&port=xxx

2、客户端对应的CommandHander如下,在返回数据中是一个List<NodeVo>,每一个NodeVo都有一个pareentId,类似于Trace实现中都会有一个parentSpanId,根据每个节点的spanid和parentSpanId就可以绘出trace调用链。

3 一个指标收集实现的流程 (基于slot 责任链)

三种入口:

  • CommonFilter
  • API方式,如Spu.entry
  • @SentinelResource

这里以CommonFilter为例,如下步骤:

SphU.entry的流程如下

每个资源对应一个SlotChain。假设服务中有200接口,那么这个chainMap大小就是200。

如果没有找到资源对应的SlotChain,通过SlotChainProvider#newSlotChain创建。最终通过DefaultSlotChainBuilder创建。

责任链的各个Slot流程如下:

40330463

Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic,指标收集)和 规则校验(rule checking)。参考:https://github.com/alibaba/Sentinel/wiki/Sentinel-%E6%A0%B8%E5%BF%83%E7%B1%BB%E8%A7%A3%E6%9E%90

 3.1 NodeSelectorSlot

1、ContextUtil中管理所有的DefautlNode资源。

2、每个请求过来都会生成一个Context,维护一个DefaultNode链,并把DefaultNode和链路关系维护到contextNameNodeMap中

3.2 ClusterBuilderSlot

生成ClusterNodde,放置在DefaultNode内部。

  • DefaultNode主要记录的调用链,即簇点的链路。
  • ClusterNode是资源的指标信息

3.3 LogSlot

没有逻辑

3.4  StatisticSlot-基于滑动窗口的指标收集StatisticNode

StatisticSlot 用于统计资源的指标信息。StaticNode是一个资源的上下文对象,在StatisticSlot中以时间窗口方式统计这个资源的请求信息,然后传递给下FlowSlot、DegradeSlot等规则slot。

1、滑动窗口和固定窗口比较

滑动窗口举例:

0~0.5s : 50

0.5~1s : 60

1~1.5s : 50

假设限流为100,如下

  • 采用固定窗口窗口,一个窗口为1s的话,那么在1~1.5的值为50,那么此时不会命中限流了
  • 采用滑动窗口,化分单位时间为多个窗口,然后多个窗口累加。可以解决1~1.5没有命中限流的问题,比如1s划分为两个窗口,滑动窗口在0.5~1.5为50+50=110,此时可以在1~1.5命中限流。

2、StaticNode采用高性能的滑动窗口数据结构 LeapArray 来统计实时的秒级指标数据。StatisticNode中定义了两个ArrayMetric来记录指标

3、WindowWrap和MetricBucket,表示窗口的指标数据。WindowWrap<MetricBuket>最小的Sentinel内部统计指标组件了,指标数据都在这里保存

  • MetricBucket是一个窗口内指标数据,包括sucess、fail、pass、block四个指标信息。
  • WindowWrap<MetricBucket>相比MetricBucket多了  窗口时间长度和起始时间戳 两个时间窗口相关的信息。

4、LeapArray,管理窗口,保存所有的窗口数据

LeapArray有两个具体实现类:

  • BucketLeapArray,分钟级别指标,每一秒是一个窗口,在指标文件中记录指标数据时,使用改数据。
  • OccupialbleBucketLeapArray,秒级指标。限流等slot使用该指标,如SlowFlot。

5、ArrayMetric标识一个指标数据,即influxdb的一行数据。

在ArrayMetric中定义了LeapArray成员,相比LeapArray提供了Metric的一些接口,如记录指标。

一个单位时间由多个窗口组成(如StaticsticsNode中rollingCounterInSecond就是一秒内划分了两个窗口),它对外提供查询指标和记录指标接口:

  • 记录接口,通过窗口WinowWarp来完成,
  • 查询接口,通过汇总一个单位时间内所有窗口WinowWrap<MetricBucket>的指标得到结果。

(1)记录一个指标数据

(2)获取success的数据, 累计每个时间窗口的sucesss的数据

3.5   FlowSlot限流实现

3.5.1 限流规则校验

1、流程

FlowSlot#checkFlow  –>  FlowRuleChecker#checkFlow –>  FlowRule#TrafficShapingContoller#canpass

3.5.2 指标写入到文件

1、FlowRuleManager开启一个记录线程

2、MetricTimerListener通过MetricWriter来写入指标

3、这些数据来自哪里?

来自StatisticsNode的rollingCounterInMinute中数据

4、文件内容

3.6 ParamFlowSlot参数限流

1、指标存储

2、规则校验

和FlowSlot比较,其实就是每个参数维护一个限流阈值,使用对应参数的该资源 的流量qps和这个参数配置的阈值进行比较。

3.7  DegradeSlot熔断降级功能实现

1、熔断降级是针对客户度服务的,CommonFilter是针对服务自身接口的。目前有两种方式使用降级,如下

  • 方式1 @SentinelResource,类似事务,需要自己根据业务常用抛出异常。
  • 方式2 API方式。如Spu.entry

2、熔断策略

整个降级策略是比较简单的,即熔断之后,间隔一个timeWindow之后,又全部打开,没有半开概念。

分类&标签