sentinel熔断简单实现
2024-01-10 06:17:40
sentinel详细介绍网址
基于qps限流
package main
import (
"fmt"
sentinel "github.com/alibaba/sentinel-golang/api"
"github.com/alibaba/sentinel-golang/core/base"
"github.com/alibaba/sentinel-golang/core/flow"
"log"
)
//基于qps配置
func main() {
//初始化sentinel
err := sentinel.InitDefault()
if err != nil {
log.Fatalf("初始化sentinel 异常:%v", err)
}
//配置限流的规则
_, err = flow.LoadRules([]*flow.Rule{
{
Resource: "some-test", //资源名称
TokenCalculateStrategy: flow.Direct, //前流量控制器的Token计算策略 目前限流
ControlBehavior: flow.Reject, //直接拒绝
Threshold: 10, //表示流控阈值
StatIntervalInMs: 1000, //1s能传10个
},
{
Resource: "some-test1", //资源名称
TokenCalculateStrategy: flow.Direct, //前流量控制器的Token计算策略 目前限流
ControlBehavior: flow.Reject, //直接拒绝
Threshold: 10, //表示流控阈值
StatIntervalInMs: 1000, //1s能传10个
},
})
if err != nil {
log.Fatalf("配置限流的规则 异常:%v", err)
}
//目前1s有10个进来
for i := 0; i < 12; i++ {
//会调用12次
e, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound)) //(base.Inbound 入口流量配置
//是否满足规则
if b != nil {
fmt.Println("限流了")
} else {
fmt.Println("检查通过")
e.Exit() //退出
}
}
}
sentinel的预热和冷启动–>在60s内逐步达到1000
package main
import (
"fmt"
sentinel "github.com/alibaba/sentinel-golang/api"
"github.com/alibaba/sentinel-golang/core/base"
"github.com/alibaba/sentinel-golang/core/flow"
"log"
"math/rand"
"time"
)
//基于qps配置
func main() {
//初始化sentinel
err := sentinel.InitDefault()
if err != nil {
log.Fatalf("初始化sentinel 异常:%v", err)
}
//配置限流的规则
_, err = flow.LoadRules([]*flow.Rule{
{
Resource: "some-test", //资源名称
TokenCalculateStrategy: flow.WarmUp, //预热/冷启动策略
ControlBehavior: flow.Reject, //直接拒绝
Threshold: 1000, //表示流控阈值
//StatIntervalInMs: 1000, //1s能传10个
WarmUpPeriodSec: 60, //预热时长 1分钟左右达到
},
{
Resource: "some-test1", //资源名称
TokenCalculateStrategy: flow.Direct, //前流量控制器的Token计算策略 目前限流
ControlBehavior: flow.Reject, //直接拒绝
Threshold: 10, //表示流控阈值
StatIntervalInMs: 1000, //1s能传10个
},
})
if err != nil {
log.Fatalf("配置限流的规则 异常:%v", err)
}
ch := make(chan struct{})
var globalTotal int
var passTotal int
var blockTotal int
//我会在每一秒统计一次,这一秒之内 你通过了多少,总共有多少, block了多少, 每一秒会产生很多的block
for i := 0; i < 100; i++ {
go func() {
for {
globalTotal++
//会调用12次
e, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound)) //(base.Inbound 入口流量配置
//是否满足规则
if b != nil {
//fmt.Println("限流了")
blockTotal++
time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
} else {
//fmt.Println("检查通过")
passTotal++
time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
e.Exit() //退出
}
}
}()
}
go func() {
var oldTotal int //过去1s总共有多少个
var oldPass int //过去1s总共pass多少个
var oldBlock int //过去1s总共block多少个
for {
oneSecondTotal := globalTotal - oldTotal
oldTotal = globalTotal
oneSecondPass := passTotal - oldPass
oldPass = passTotal
oneSecondBlock := blockTotal - oldBlock
oldBlock = blockTotal
time.Sleep(time.Second)
fmt.Printf("total:%d, pass:%d, block:%d\n", oneSecondTotal, oneSecondPass, oneSecondBlock)
}
}()
<-ch
}
匀速通过,更换掉就行,比如一秒你有100个通过,那么就是每10ms通过一个,那么就需要延迟10ms就会全部通过
sentinel的熔断接口
基于错误数
// Copyright 1999-2020 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"errors"
"fmt"
"log"
"math/rand"
"time"
sentinel "github.com/alibaba/sentinel-golang/api"
"github.com/alibaba/sentinel-golang/core/circuitbreaker"
"github.com/alibaba/sentinel-golang/core/config"
"github.com/alibaba/sentinel-golang/logging"
"github.com/alibaba/sentinel-golang/util"
)
type stateChangeTestListener struct {
}
func (s *stateChangeTestListener) OnTransformToClosed(prev circuitbreaker.State, rule circuitbreaker.Rule) {
fmt.Printf("rule.steategy: %+v, From %s to Closed, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
}
func (s *stateChangeTestListener) OnTransformToOpen(prev circuitbreaker.State, rule circuitbreaker.Rule, snapshot interface{}) {
fmt.Printf("rule.steategy: %+v, From %s to Open, snapshot: %d, time: %d\n", rule.Strategy, prev.String(), snapshot, util.CurrentTimeMillis())
}
func (s *stateChangeTestListener) OnTransformToHalfOpen(prev circuitbreaker.State, rule circuitbreaker.Rule) {
fmt.Printf("rule.steategy: %+v, From %s to Half-Open, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
}
func main() {
total := 0
totalPass := 0
totalBlock := 0
totalErr := 0
//创建配置对象
conf := config.NewDefaultConfig()
// for testing, logging output to console
conf.Sentinel.Log.Logger = logging.NewConsoleLogger() //加入loging
err := sentinel.InitWithConfig(conf)
if err != nil {
log.Fatal(err)
}
ch := make(chan struct{})
// Register a state change listener so that we could observer the state change of the internal circuit breaker.
circuitbreaker.RegisterStateChangeListeners(&stateChangeTestListener{}) //注册,当内部状态转换加一个自己的逻辑
_, err = circuitbreaker.LoadRules([]*circuitbreaker.Rule{
// Statistic time span=5s, recoveryTimeout=3s, maxErrorCount=50
{
Resource: "abc",
Strategy: circuitbreaker.ErrorCount,
RetryTimeoutMs: 3000, //3s之后进入half-open
MinRequestAmount: 10, //静默数
StatIntervalMs: 5000, //5s统计一次
StatSlidingWindowBucketCount: 10, //活动窗口的个数
Threshold: 50, //数量不超过50个
},
})
fmt.Println(circuitbreaker.ErrorCount)
if err != nil {
log.Fatal(err)
}
logging.Info("[CircuitBreaker ErrorCount] Sentinel Go circuit breaking demo is running. You may see the pass/block metric in the metric log.")
go func() {
for {
total++
e, b := sentinel.Entry("abc")
if b != nil {
totalBlock++
fmt.Println("协程熔断了")
// g1 blocked
time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)
} else {
totalPass++
if rand.Uint64()%20 > 9 {
totalErr++
// Record current invocation as error.
sentinel.TraceError(e, errors.New("biz error"))
}
// g1 passed
time.Sleep(time.Duration(rand.Uint64()%80+10) * time.Millisecond)
e.Exit()
}
}
}()
go func() {
for {
total++
e, b := sentinel.Entry("abc")
if b != nil {
totalBlock++
// g2 blocked
time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)
} else {
// g2 passed
totalPass++
time.Sleep(time.Duration(rand.Uint64()%80) * time.Millisecond)
e.Exit()
}
}
}()
go func() {
for {
time.Sleep(time.Second)
fmt.Println(totalErr)
}
}()
<-ch
}
具体需要修改源码的测试
文章来源:https://blog.csdn.net/qq_40432598/article/details/135447823
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!