27

gin框架sentinel流量控制初体验

 3 years ago
source link: https://studygolang.com/articles/31032
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
J36BveQ.png!mobile

image.png

流量控制设计理念

流量控制有以下几个角度:

  • 资源和资源之间的关系;
  • 运行指标,例如 QPS、线程池、系统负载等;
  • 控制的效果,例如直接限流、冷启动、匀速+排队等待等。

Sentinel提供了几个组件让用户去实现相关的流控方案:

  1. 基于QPS的流量控制: 流量控制
  2. 基于协程数的隔离流控: 并发隔离控制
  3. 基于热点参数的流量控制: 热点参数限流
  4. 基于系统指标的自适应流控: 系统自适应流控

Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

https://github.com/alibaba/sentinel-golang

demo:

package main

import (
    sentinelPlugin "github.com/alibaba/sentinel-golang/adapter/gin"
    sentinel "github.com/alibaba/sentinel-golang/api"
    "github.com/alibaba/sentinel-golang/core/base"
    "github.com/alibaba/sentinel-golang/core/config"
    "github.com/alibaba/sentinel-golang/core/flow"
    "github.com/alibaba/sentinel-golang/logging"
    "github.com/gin-gonic/gin"
    "log"
    "math/rand"
    "time"
)

func init() {
    //初始化 sentinel
    conf := config.NewDefaultConfig()
    conf.Sentinel.Log.Logger = logging.NewConsoleLogger("cb-integration-normal")
    conf.Sentinel.Log.Dir = "."
    err := sentinel.InitWithConfig(conf)
    if err != nil {
        log.Fatal("err",err)
    }

    //go语言实现暂未发现appLimit即限制客户端每秒请求次数
    if _, err := flow.LoadRules([]*flow.Rule{
        {
            Resource:               "GET:/health",
            MetricType:             flow.QPS,
            Count:                  1,
            TokenCalculateStrategy: flow.Direct,
            ControlBehavior:        flow.Reject,
        },
    });err != nil {
        log.Fatalf("Unexpected error: %+v", err)
        return
    }

}

func main() {
    r := gin.Default()
    // Sentinel 会对每个 API route 进行统计,资源名称类似于 GET:/foo/:id
    // 默认的限流处理逻辑是返回 429 (Too Many Requests) 错误码,支持配置自定义的 fallback 逻辑
    r.Use(sentinelPlugin.SentinelMiddleware())

    _, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound))
    if b != nil {
        // Blocked. We could get the block reason from the BlockError.
        time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
    }else {
        r.GET("/health", func(context *gin.Context) {
            context.JSON(200, map[string]string{"status":"ok"})
        })
    }

    _ = r.Run("0.0.0.0:8080")
}

有疑问加站长微信联系

iiUfA3j.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK