网站优化关键词怎么做,小红书推广平台有哪些,浙浙江省建设信息港,杭州做企业网站公司随着微服务的流行#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件#xff0c;主要以流量为切入点#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开…随着微服务的流行服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件主要以流量为切入点从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 文档
1.新手指南
资源的定义可以是应用、接口、函数或一段代码目的是保护这段资源的运行。
1.1使用方法
通用配置及初始化配置方式使用文档
InitDefault()从环境变量指定的配置文件以及环境变量中读取相应配置来初始化 Sentinel若环境变量不存在则使用默认值。Init(configPath string)从给定的 YAML 文件中读取相应配置来初始化 Sentinel。InitWithConfig(confEntity *config.Entity): 用户硬编码配置对象*config.Entity来初始化Sentinel。 **埋点定义资源**每个埋点都有一个资源名称代表触发了这个资源的调用和访问 Entry(resource string, opts ...Option) (*base.SentinelEntry, *base.BlockError)
resource表示资源名称opts表示埋点配置。返回值列表的第一个参数和第二个参数是互斥的如果pass的话就会返回(*base.SentinelEntry, nil)如果执行blocked那么Sentinel会返回(nil, *base.BlockError)
埋点配置
WithTrafficType(entryType base.TrafficType)标记该埋点资源的流量类型其中 Inbound 代表入口流量Outbound 代表出口流量。若不指定默认为 Outbound。WithResourceType(resourceType base.ResourceType)标记该埋点资源的分类。WithAcquireCount(acquireCount uint32)标记每次触发该埋点计为几次调用可以理解为 batch count。若不指定默认为 1。WithArgs(args ...interface{})埋点携带的参数列表为热点参数统计预留。WithSlotChain(chain *base.SlotChain)埋点执行的检查的slotchain若不指定默认使用全局slotchain
示例在这里假设业务逻辑是很复杂的函数记作ExcuteSteps所以在Exit的时候可以使用defer
import (sentinel github.com/alibaba/sentinel-golang/api
)// Entry 方法用于埋点
e, b : sentinel.Entry(resource-name, sentinel.WithTrafficType(base.Inbound))
if b ! nil {// 请求被流控可以从 BlockError 中获取限流详情// block 后不需要进行 Exit()
} else {// 请求可以通过// 务必保证业务逻辑结束后 Exitdefer e.Exit()
}
ExcuteSteps()规则配置支持硬编码方式或是动态数据源 流控规则为例 _, err flow.LoadRules([]*flow.Rule{{Resource: some-test,Threshold: 10,TokenCalculateStrategy: flow.Direct,ControlBehavior: flow.Reject,},
})
if err ! nil {// 加载规则失败进行相关处理
}1.2规则配置 Sentinel Go支持 流控规则、流量隔离规则并发控制、熔断规则、自适应过载保护规则和热点参数流控规则。 基于QPS限流的完整示例 import (sentinel github.com/alibaba/sentinel-golang/api
)func main() {// 务必先进行初始化err : sentinel.InitDefault()if err ! nil {log.Fatal(err)}// 配置一条限流规则_, err flow.LoadRules([]*flow.Rule{{Resource: some-test,Threshold: 10,TokenCalculateStrategy: flow.Direct,ControlBehavior: flow.Reject,},})if err ! nil {fmt.Println(err)return}ch : make(chan struct{})for i : 0; i 10; i {go func() {for {// 埋点逻辑埋点资源名为 some-teste, b : sentinel.Entry(some-test)if b ! nil {// 请求被拒绝在此处进行处理time.Sleep(time.Duration(rand.Uint64() % 10) * time.Millisecond)} else {// 请求允许通过此处编写业务逻辑fmt.Println(util.CurrentTimeMillis(), Passed)time.Sleep(time.Duration(rand.Uint64() % 10) * time.Millisecond)// 务必保证业务结束后调用 Exite.Exit()}}}()}-ch
}2.流量控制
流量控制是监控资源的统计指标根据token计算策略来计算资源的可用token阈值根据流量控制策略对请求进行控制避免被瞬时的流量高峰冲垮从而保障应用的高可用性。
Sentinel 通过定义流控规则来实现对 Resource 的流量控制。在Sentinel内部会在加载流控规则时候将每个 flow.Rule 都会被转换成流量控制器(TrafficShapingController)。 每个流量控制器实例都会有自己独立的统计结构这里统计结构是一个滑动窗口。Sentinel 内部会尽可能复用 Resource 级别的全局滑动窗口如果流控规则的统计设置没法复用Resource的全局统计结构那么Sentinel为流量控制器创建一个全新的私有的滑动窗口然后通过 flow.StandaloneStatSlot 这个统计Slot来维护统计指标。
2.1流控规则
type Rule struct {ID string json:id,omitempty //ID表示规则的唯一ID可选Resource string json:resource //资源名字TokenCalculateStrategy TokenCalculateStrategy json:tokenCalculateStrategy //当前流量控制器的Token计算策略。Direct表示直接使用字段 Threshold 作为阈值WarmUp表示使用预热方式计算Token的阈值。ControlBehavior ControlBehavior json:controlBehavior//表示流量控制器的控制策略Reject表示超过阈值直接拒绝Throttling表示匀速排队。Threshold float64 json:threshold//表示流控阈值 RelationStrategy RelationStrategy json:relationStrategy// 调用关系限流策略RefResource string json:refResource //关联的resourceMaxQueueingTimeMs uint32 json:maxQueueingTimeMs //匀速排队的最大等待时间WarmUpPeriodSec uint32 json:warmUpPeriodSec //预热的时间长度WarmUpColdFactor uint32 json:warmUpColdFactor//预热的因子默认是3该值的设置会影响预热的速度StatIntervalInMs uint32 json:statIntervalInMs//规则对应的流量控制器的独立统计结构的统计周期
}补充
如果字段StatIntervalInMs是1000(也就是1秒)那么Threshold就表示QPS流量控制器也就会依据资源的QPS来做流控。
RelationStrategy: 调用关系限流策略CurrentResource表示使用当前规则的resource做流控AssociatedResource表示使用关联的resource做流控关联的resource在字段 RefResource 定义
这里特别强调一下 StatIntervalInMs 和 Threshold 这两个字段这两个字段决定了流量控制器的灵敏度。以 Direct Reject 的流控策略为例流量控制器的行为就是在 StatIntervalInMs 周期内允许的最大请求数量是Threshold。比如如果 StatIntervalInMs 是 10000Threshold 是10000那么流量控制器的行为就是控制该资源10s内运行最多10000次访问。
2.2流量控制策略
由规则里的TokenCalculateStrategy 和 ControlBehavior 两个字段决定。
TokenCalculateStrategy 表示流量控制器的Token计算方式
Direct表示直接使用规则中的 Threshold 表示当前统计周期内的最大Token数量。WarmUp表示通过预热的方式计算当前统计周期内的最大Token数量预热的计算方式会根据规则中的字段 WarmUpPeriodSec 和 WarmUpColdFactor 来决定预热的曲线。
字段 ControlBehavior 表示表示流量控制器的控制行为
Reject表示如果当前统计周期内统计结构统计的请求数超过了阈值就直接拒绝。Throttling表示匀速排队的统计策略。它的中心思想是以固定的间隔时间让请求通过。当请求到来的时候如果当前请求距离上个通过的请求通过的时间间隔不小于预设值则让当前请求通过否则计算当前请求的预期通过时间如果该请求的预期通过时间小于规则预设的 timeout 时间则该请求会等待直到预设时间到来通过排队等待处理若预期的通过时间超出最大排队时长则直接拒接这个请求。主要用于处理间隔性突发的流量例如消息队列在某一秒有大量的请求到来而接下来的几秒则处于空闲状态我们希望系统能够在接下来的空闲期间逐渐处理这些请求而不是在第一秒直接拒绝多余的请求。
2.3流量控制器的统计结构
每个流量控制器实例都会有自己独立的统计结构。流量控制器的统计结构由规则中的 StatIntervalInMs 字段设置StatIntervalInMs表示统计结构的统计周期。Sentinel 默认会为每个Resource创建一个全局的滑动窗口统计结构这个全局的统计结构默认是一个间隔为10s,20个格子的滑动窗口也就是每个统计窗口长度是500ms。
流量控制器实例会尽可能复用这个Resource级别的全局统计结构复用逻辑原则是优先复用Resource级别的全局统计结构如果不可复用就重新创建一个独立的滑动窗口统计结构(BucketLeapArray)具体的逻辑细节如下
如果StatIntervalInMs大于全局滑动窗口的间隔(默认10s)那么将不可复用全局统计结构。Sentinel会给流量控制器创建一个长度是StatIntervalInMs格子数是1的全新统计结构这个全新的统计结构由Sentinel内部的StandaloneStatSlot来维护统计。如果StatIntervalInMs小于全局滑动窗口的窗口长度(默认是500ms), 那么将不可复用全局统计结构。Sentinel会给流量控制器创建一个长度是StatIntervalInMs格子数是1的全新统计结构这个全新的统计结构由Sentinel内部的StandaloneStatSlot来维护统计。如果StatIntervalInMs在集合[全局滑动窗口的窗口长度全局滑动窗口的间隔]之间首先需要计算格子数如果StatIntervalInMs可以被全局滑动窗口的窗口长度(默认是500ms)整除那么格子数就为 StatIntervalInMs/GlobalStatisticBucketLengthInMs如果不可整除格子数是1。然后会调用 core/base/CheckValidityForReuseStatistic函数来判断当前统计结构间隔和格子数是否可以复用全局统计结构。如果可以复用就会基于resource级别的全局统计结构ResourceNode创建SlidingWindowSlidingWindow是一个虚拟结构SlidingWindow只可读而且读的数据是通过聚合ResourceNode数据得到的。如果不可复用就使用统计结构间隔和格子数创建全新的滑动窗口(BucketLeapArray)。
CheckValidityForReuseStatistic函数参考https://github.com/alibaba/sentinel-golang/blob/master/core/base/stat.go#func CheckValidityForReuseStatistic
基于规则创建统计结构的逻辑参考https://github.com/alibaba/sentinel-golang/blob/master/core/flow/rule_manager.go#func generateStatFor
2.4常见场景的规则配置
2.4.1基于QPS对某个资源限流
{Resource: some-test,TokenCalculateStrategy: flow.Direct,ControlBehavior: flow.Reject,Threshold: 500,StatIntervalInMs: 1000,
}StatIntervalInMs必须是1000表示统计周期是1s那么Threshold所配置的值也就是QPS的阈值
2.4.2基于一定统计间隔时间来控制总的请求数
{Resource: some-test,TokenCalculateStrategy: flow.Direct,ControlBehavior: flow.Reject,Threshold: 10000,StatIntervalInMs: 10000,
}在一定统计周期内控制请求的总量。比如上面的例子指的是在10000ms10s里的最大请求数是10000。但是对于脉冲类型流量的抵抗力很弱
2.4.3毫秒级别流控
如果一些流量在毫秒级别的波动很大那建议StatIntervalInMs的配置在毫秒级别除非特殊场景建议配置的值为100ms的倍数比如100200这种。这种相当于缩小了统计周期将QPS的周期缩小了10倍控制周期降低到了100ms。这种配置能够很好的应对脉冲流量保障系统稳定性比如sample:
{Resource: some-test,TokenCalculateStrategy: flow.Direct,ControlBehavior: flow.Reject,Threshold: 80,StatIntervalInMs: 100,
}上面限制了100ms的阈值是80实际QPS大概是800。
注意这种配置也是有缺点的脉冲流量很大可能造成有损(会拒绝很多流量)。
2.4.4脉冲流量无损
针对前面第三点场景如果既想控制流量曲线又想无损一般做法是通过匀速排队的控制策略平滑掉流量。
2.4.5基于调用关系的流量控制
Sentinel 支持关联流量控制策略。当两个资源之间具有资源争抢或者依赖关系的时候这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢读的速度过高会影响写得速度写的速度过高会影响读的速度。如果放任读写操作争抢资源则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢。
2.5 demo
示例
3. 熔断降级
现在的分布式架构里一个服务常常会调用第三方服务比如另一个RPC接口、数据库、API等。如果依赖的外部服务出现了不稳定的情况比如请求的响应时间变长那么服务自身调用第三方服务的响应时间也会变长自身的线程可能会产生堆积耗尽业务自身的线程池最终服务本身也变得不可用。因此我们需要对不稳定的 弱依赖服务调用 进行 熔断降级暂时切断不稳定的服务调用避免局部不稳定因素导致整个分布式系统的雪崩。熔断降级作为保护服务自身的手段通常在**客户端调用端**进行配置。 比如A服务需要调用B服务的接口在A服务里需要配置熔断器避免B服务不稳定从而拖垮A服务。
3.1 熔断器模型
熔断器内部维护了一个状态机
CLOSED状态初始状态熔断器保持闭合对资源的访问通过熔断器的检查OPEN状态断开状态熔断器开启切断对资源的访问HALF OPEN半开状态周期性的允许一定数目的探测请求通过。如果探测请求能够正常的返回则探测成功转换到CLOSED状态结束熔断探测失败回滚到OPEN状态。
3.2 熔断器的设计
衡量下游服务质量指标是RT、异常数量和异常比例等等。支持三种熔断策略慢调用比例熔断、异常比例熔断和异常数量熔断。 用户通过设置熔断规则(Rule)来给资源添加熔断器。Sentinel会将每一个熔断规则转换成对应的熔断器熔断器对用户是不可见的。Sentinel 的每个熔断器都会有自己独立的统计结构。
熔断器的整体检查逻辑可以用几点来精简概括
基于熔断器的状态机来判断对资源是否可以访问对不可访问的资源会有探测机制探测机制保障了对资源访问的弹性恢复熔断器会在对资源访问的完成态去更新统计然后基于熔断规则更新熔断器状态机。
3.3 熔断策略
静默期 三种熔断策略都支持静默期静默期指的是最小的静默请求数在一个统计周期里如果对资源的请求数小于设置的静默数熔断器不会基于统计值去更改熔断器的状态。 比如在统计周期刚开始的时候第一个请求恰好是慢请求这时候慢调用比例是100%显然不合理。静默期提高了熔断器的精准性且降低了误判的可能性。 支持的几种熔断策略前提都是不在静默期 **慢调用比例策略**慢调用的比例大于设置的阈值需要设置RT临界值最大响应时间对该资源访问的响应时间大于该阈值即为慢调用。 错误比例策略 统计周期内资源请求访问异常的比例大于阈值。 错误计数策略 请求访问异常数大于设定的阈值。 如果规则指定熔断器策略采用错误比例或则错误计数那么为了统计错误比例或错误计数需要调用API api.TraceError(entry, err) 埋点每个请求的业务异常。 3.4 熔断降级规则定义
// Rule encompasses the fields of circuit breaking rule.
type Rule struct {Id string json:id,omitempty//全局唯一ID 可选Resource string json:resource //资源名称Strategy Strategy json:strategy //熔断策略RetryTimeoutMs uint32 json:retryTimeoutMs//熔断出发后持续时间 msMinRequestAmount uint64 json:minRequestAmount //静默数量StatIntervalMs uint32 json:statIntervalMs //统计的时间窗口长度 msMaxAllowedRtMs uint64 json:maxAllowedRtMs //最大响应时间Threshold float64 json:threshold //阈值
}补充说明 Strategy: 熔断策略目前支持SlowRequestRatio、ErrorRatio、ErrorCount三种
选择以慢调用比例(SlowRequestRatio) 作为阈值需要设置允许的最大响应时间MaxAllowedRtMs**请求的响应时间大于该值则统计为慢调用**。通过Threshold字段设置触发熔断的慢调用比例取值范围为[0.0, 1.0]。规则配置后**在单位统计时长内请求数目大于设置的最小请求数目(静默期)并且慢调用的比例大于阈值**则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态若接下来的一个请求响应时间小于设置的最大 RT则结束熔断若大于设置的最大RT 则会再次被熔断。选择以错误比例 (ErrorRatio) 作为阈值需要设置触发熔断的异常比例Threshold取值范围为 [0.0, 1.0]。规则配置后在单位统计时长内请求数目大于设置的最小请求数目并且异常的比例大于阈值则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态若接下来的一个请求没有错误则结束熔断否则会再次被熔断。代码中可以通过 api.TraceError(entry, err) 函数来记录 error。
Threshold: 对于慢调用熔断策略,Threshold表示是慢调用比例的阈值(小数表示比如0.1表示10%)也就是如果当前资源的慢调用比例如果高于Threshold那么熔断器就会断开否则保持闭合状态。 对于错误比例策略Threshold表示的是错误比例的阈值(小数表示比如0.1表示10%)。对于错误数策略Threshold是错误计数的阈值
Resource、Strategy、RetryTimeoutMs、MinRequestAmount、StatIntervalMs、Threshold 每个规则都必设的字段MaxAllowedRtMs是慢调用比例熔断规则必设的字段。 MaxAllowedRtMs 字段仅仅对慢调用比例 (SlowRequestRatio) 策略有效对其余策略均属于无效字段。 StatIntervalMs 表示熔断器的统计周期单位是毫秒这个值我们不建议设置的太大或则太小一般情况下设置10秒左右都OK当然也要根据实际情况来适当调整。 RetryTimeoutMs 的设置需要根据实际情况设置探测周期一般情况下设置10秒左右都OK当然也要根据实际情况来适当调整。
配置参考
// 慢调用比例规则
rule1 : Rule{Resource: abc,Strategy: SlowRequestRatio,RetryTimeoutMs: 5000,MinRequestAmount: 10,StatIntervalMs: 10000,MaxAllowedRtMs: 20,Threshold: 0.1,
},
// 错误比例规则
rule1 : Rule{Resource: abc,Strategy: ErrorRatio,RetryTimeoutMs: 5000,MinRequestAmount: 10,StatIntervalMs: 10000,Threshold: 0.1,
},
// 错误计数规则
rule1 : Rule{Resource: abc,Strategy: ErrorCount,RetryTimeoutMs: 5000,MinRequestAmount: 10,StatIntervalMs: 10000,Threshold: 100,
},3.5 最佳场景实践
熔断器一般用于应用对外部资源访问时的保护措施。这里简单描述一些场景
分布式系统中降级假设存在应用A需要调用应用B的接口(特别是一些对接外部公司或者业务的接口时候)那么一般用于A调用B的接口时的防护数据库慢调用的防护 假设应用需要读/写数据库但是该读写SQL存在潜在慢SQL的可能性那么可以对该读写接口做防护当接口不稳定时候(存在慢SQL)那么基于熔断器做降级。也可以是应用中任意弱依赖接口做降级防护即自动降级后不影响业务核心链路。
3.6 demo
demo
4. 并发隔离控制
并发隔离控制是基于资源访问的并发协程数来控制对资源的访问也就是控制资源访问的最大并发数避免因为资源的异常导致协程耗尽。
4.1 隔离规则
// Rule describes the concurrency num control, that is similar to semaphore
type Rule struct {ID string json:id,omitemptyResource string json:resource //资源名称MetricType MetricType json:metricType//目标度量类型Threshold uint32 json:threshold//阈值
}配置示例其中Concurrency表示并发数如果资源的当前并发数超过阈值资源将不可访问。
r1 : Rule{Resource: abc,MetricType: Concurrency,Threshold: 100,
}4.2 最佳实践场景
在客户端调用端 做一层软隔离并发隔离控制达到对资源访问的并发控制的目的
4.3 demo
demo
package mainimport (sentinel github.com/alibaba/sentinel-golang/apigithub.com/alibaba/sentinel-golang/core/configgithub.com/alibaba/sentinel-golang/core/isolationgithub.com/alibaba/sentinel-golang/loggingmath/randostestingtime
)func Test_concurrency_limitation(t *testing.T) {cfg : config.NewDefaultConfig() //生成默认配置cfg.Sentinel.Log.Logger logging.NewConsoleLogger() //控制台日志err : sentinel.InitWithConfig(cfg) //初始化if err ! nil {logging.Error(err, fail)os.Exit(1)}logging.ResetGlobalLoggerLevel(logging.DebugLevel) //设置日志级别 debugch : make(chan struct{}) //通道r1 : isolation.Rule{ //定义规则Resource: abc,MetricType: isolation.Concurrency, //并发数Threshold: 12, //阈值} //并发数12触发熔断器_, err isolation.LoadRules([]*isolation.Rule{r1})if err ! nil {logging.Error(err, fail)os.Exit(1)}for i : 0; i 15; i { //开辟15个协程go func() {for {e, b : sentinel.Entry(abc, sentinel.WithBatchCount(1)) //WithBatchCount 表示每次占用的资源个数if b ! nil { //限流logging.Info([Isolation] Blocked, reason, b.BlockType().String(), rule, b.TriggeredRule(), snapshot, b.TriggeredValue())time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)} else { //通过 处理业务逻辑logging.Info([Isolation] Passed)time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)e.Exit() //务必要写}}}()}-ch //保证主进程不退出
} 5.源码
阿里 双11 同款流量防卫兵 Sentinel go 源码解读 Sentinel-Go 源码系列一开篇 Sentinel Go 核心统计结构滑动窗口的深度解析