快速上手 sentinel-golang


写本文的初衷挺简单的,官方文档有些复杂,磕磕碰碰太多,特此记录一下怎么弄。

ps : 官方文档可能太久没更新了,挺多东西跟包里还是有区别的

安装

go get -u github.com/alibaba/sentinel-golang

导入

此处建议配置成一样的,后面比较好 copy (^_^)

import(
    sentinel "github.com/alibaba/sentinel-golang/api"
)

Demos

1.流量控制

这是一个简单的 demo ,请自己跑起来试试,并且根据下面的流控规则,理解如何去编写规则。

package main

import (
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/base"
	"github.com/alibaba/sentinel-golang/core/flow"
	"github.com/gin-gonic/gin"
)

// Sentinel 中间件
func Sentinel(resource string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 通过api.Entry创建一个资源的访问入口,如果资源的访问量超过了限流规则中的阈值,就会返回限流错误
		e, b := sentinel.Entry(resource, sentinel.WithTrafficType(base.Inbound))
		if b != nil {
			c.JSON(429, gin.H{
				"err": "too many requests",
			})
			c.Abort()
			return
		}
		defer e.Exit()
		c.Next()
	}
}

func main() {
	sentinel.InitDefault()
	flow.LoadRules([]*flow.Rule{
		{
			// 资源名称
			Resource: "/ping",
			TokenCalculateStrategy: flow.Direct,
			ControlBehavior: flow.Reject,
			Threshold: 1,
			StatIntervalInMs: 1000,
			RelationStrategy: flow.CurrentResource,
		},
	})
	r := gin.Default()
	r.GET("/ping", Sentinel("/ping"), func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run(":8888")
}

2.熔断降级

流量控制

流控规则

下表整理了流量控制的各项配置参数及其描述:

配置参数json 标识描述类型示例备注
Resourceresource资源名称,示例值为 “/ping”string“/ping”
TokenCalculateStrategytokenCalculateStrategyToken计算策略:
Direct(直接阈值)
WarmUp(预热计算)
MemoryAdaptive(内存自适应调整)
flow.TokenCalculateStrategyflow.Direct
ControlBehaviorcontrolBehavior流控策略:
Reject(直接拒绝)
Throttling(匀速排队)
flow.ControlBehaviorflow.Reject
Thresholdthreshold限流阈值,示例中每秒1次请求float64100
StatIntervalInMsstatIntervalInMs统计时间窗口,单位毫秒,示例中为1000msuint32(单位是 ms)1000
RelationStrategyrelationStrategy调用关系限流策略:
CurrentResource(当前资源限流)
AssociatedResource(关联资源限流)
flow.RelationStrategyflow.CurrentResource此处主要的使用场景是:存在 A 策略需要占用 B 策略的资源。此时使用此参数(建议一个接口用一个 resource)
RefResourcerefResource关联的资源名称,对应AssociatedResource策略string
WarmUpPeriodSecwarmUpPeriodSec预热时间长度,单位秒,仅WarmUp策略有效uint3210
WarmUpColdFactorwarmUpColdFactor预热因子,默认为3,影响预热速度,仅WarmUp策略有效uint323
MaxQueueingTimeMsmaxQueueingTimeMs匀速排队的最大等待时间,单位毫秒,仅在 ControlBehavior 使用 Throttling 时有效uint32
LowMemUsageThresholdlowMemUsageThreshold低内存使用率阈值,内存使用率低于此值时流控阈值降低,仅 MemoryAdaptive 策略有效int64
HighMemUsageThresholdhighMemUsageThreshold高内存使用率阈值,内存使用率高于此值时流控阈值升高,仅 MemoryAdaptive 策略有效int64
MemLowWaterMarkBytesmemLowWaterMarkBytes内存使用率低水位,低于此值流控阈值降低,仅 MemoryAdaptive 策略有效int64
MemHighWaterMarkBytesmemHighWaterMarkBytes内存使用率高水位,高于此值流控阈值升高,仅 MemoryAdaptive 策略有效int64

并发隔离控制

系统自适应流控

Sentinel 系统自适应流控从整体维度对应用入口流量进行控制,结合系统的 Load、CPU 使用率以及应用的入口 QPS、平均响应时间和并发量等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应用整体维度的,而不是单个调用维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(埋点的 TrafficType 为 Inbound),比如 Web 服务或 gRPC provider 接收的请求,都属于入口流量。

规则配置方法如下

import "github.com/alibaba/sentinel-golang/core/system"

func loadSystemRule(){
    // 自适应流控,启发因子为 load1 >= 8
    _, err := system.LoadRules([]*system.Rule{
		{
			MetricType:   system.Load,
			TriggerCount: 8.0,
			Strategy:     system.BBR,
		},
	})
}

规则

字段描述类型示例备注
MetricType触发度量的类型:
Load:表示Linux/Unix系统的负载(load average)
AvgRT:表示所有入站请求的平均响应时间
Concurrency:表示所有入站请求的并发数
InboundQPS:表示所有入站请求的每秒查询率(QPS)
CpuUsage:表示系统的CPU使用率百分比
MetricTypeSize:表示MetricType枚举的大小,通常用于枚举边界检查
system.MetricTypesystem.Load
TriggerCount自适应策略的触发阈值下限float6480.0
Strategy自适应策略system.AdaptiveStrategyReduceRequests

热点参数流控

熔断降级

动态数据源

本地文件

本方法可以动态监视本地数据规则。

编写 rules.json

[
  {
    "resource": "/ping",
    "tokenCalculateStrategy": 0,
    "controlBehavior": 0,
    "threshold": 0.0,
    "relationStrategy": 0
  }
]
package main

import (
	"github.com/alibaba/sentinel-golang/ext/datasource"
	"github.com/alibaba/sentinel-golang/ext/datasource/file"
)

func loadRulesFromFile(filePath string) error {
	// 注册流控规则数据源
    // 对于不同的数据去向,再次进行调整
    // 此处使用的是规则文件,因此使用的是 FlowRuleJsonArrayParser
	h := datasource.NewDefaultPropertyHandler(datasource.FlowRuleJsonArrayParser, datasource.FlowRulesUpdater)
	ds := file.NewFileDataSource(filePath, h)
	err := ds.Initialize()
	if err != nil {
		return err
	}
	src, err := ds.ReadSource()
	if err != nil {
		return err
	}
	err = ds.Handle(src)
	if err != nil {
		return err
	}
	return nil

}

在主函数中初始化后调用loadRulesFromFile即可

package main

import (
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/base"
	"github.com/gin-gonic/gin"
)

// Sentinel 中间件
func Sentinel(resource string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 通过api.Entry创建一个资源的访问入口,如果资源的访问量超过了限流规则中的阈值,就会返回限流错误
		// 此处埋点的是
		e, b := sentinel.Entry(resource, sentinel.WithTrafficType(base.Inbound))
		if b != nil {
			c.JSON(429, gin.H{
				"err": "too many requests",
			})
			c.Abort()
			return
		}
		defer e.Exit()
		c.Next()
	}
}

func main() {
	sentinel.InitDefault()
	// 初始化后加载规则
	loadRulesFromFile("./rules.json")
	//flow.LoadRules([]*flow.Rule{
	//	{
	//		// 资源名称
	//		Resource:               "/ping",
	//		TokenCalculateStrategy: flow.Direct,
	//		ControlBehavior:        flow.Reject,
	//		Threshold:              1,
	//		StatIntervalInMs:       1000,
	//		RelationStrategy:       flow.CurrentResource,
	//	},
	//})
	r := gin.Default()
	r.GET("/ping", Sentinel("/ping"), func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run(":8888")
}

etcd

todo


如果本文帮助到了你,帮我点个广告可以咩(o′┏▽┓`o)


评论
  目录