快速上手 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 标识 描述 类型 示例 备注
Resource resource 资源名称,示例值为 “/ping” string “/ping”
TokenCalculateStrategy tokenCalculateStrategy Token计算策略:
Direct(直接阈值)
WarmUp(预热计算)
MemoryAdaptive(内存自适应调整)
flow.TokenCalculateStrategy flow.Direct
ControlBehavior controlBehavior 流控策略:
Reject(直接拒绝)
Throttling(匀速排队)
flow.ControlBehavior flow.Reject
Threshold threshold 限流阈值,示例中每秒1次请求 float64 100
StatIntervalInMs statIntervalInMs 统计时间窗口,单位毫秒,示例中为1000ms uint32(单位是 ms) 1000
RelationStrategy relationStrategy 调用关系限流策略:
CurrentResource(当前资源限流)
AssociatedResource(关联资源限流)
flow.RelationStrategy flow.CurrentResource 此处主要的使用场景是:存在 A 策略需要占用 B 策略的资源。此时使用此参数(建议一个接口用一个 resource)
RefResource refResource 关联的资源名称,对应AssociatedResource策略 string
WarmUpPeriodSec warmUpPeriodSec 预热时间长度,单位秒,仅WarmUp策略有效 uint32 10
WarmUpColdFactor warmUpColdFactor 预热因子,默认为3,影响预热速度,仅WarmUp策略有效 uint32 3
MaxQueueingTimeMs maxQueueingTimeMs 匀速排队的最大等待时间,单位毫秒,仅在 ControlBehavior 使用 Throttling 时有效 uint32
LowMemUsageThreshold lowMemUsageThreshold 低内存使用率阈值,内存使用率低于此值时流控阈值降低,仅 MemoryAdaptive 策略有效 int64
HighMemUsageThreshold highMemUsageThreshold 高内存使用率阈值,内存使用率高于此值时流控阈值升高,仅 MemoryAdaptive 策略有效 int64
MemLowWaterMarkBytes memLowWaterMarkBytes 内存使用率低水位,低于此值流控阈值降低,仅 MemoryAdaptive 策略有效 int64
MemHighWaterMarkBytes memHighWaterMarkBytes 内存使用率高水位,高于此值流控阈值升高,仅 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.MetricType system.Load
TriggerCount 自适应策略的触发阈值下限 float64 80.0
Strategy 自适应策略 system.AdaptiveStrategy ReduceRequests

热点参数流控

熔断降级

动态数据源

本地文件

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

编写 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)


文章作者: Anubis
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Anubis !
评论
  目录