Maison > Article > développement back-end > Que sont la limitation de courant et la fusion ? Explication détaillée de la dégradation du fusible limiteur de courant Sentinel
Cet article vous est présenté par la rubrique tutoriel golang sur la limitation de courant Sentinel et la dégradation des disjoncteurs. Le contenu comprend une introduction à la limitation de courant et au disjoncteur, ainsi que Sentinel open source alibaba, l'installation et une introduction pratique. j'espère que cela sera utile à des amis dans le besoin !
Qu'est-ce que le déclassement du disjoncteur limiteur de courant
Limitation de courant : dans notre système acquis, si une grande quantité de trafic entre soudainement ce jour-là, notre service ne peut que le faire ? gérer un maximum de 2 000 requêtes en même temps, et soudainement 5 000 requêtes sont arrivées. N'est-ce pas une pression terrible sur le serveur ? Cela peut directement provoquer une panne et un crash du serveur, empêchant le volume de traitement 2K d'origine de fonctionner ? À ce stade, nous devons limiter le flux. La fonction de la limite de flux est de maintenir le nombre de visites sur le serveur au plus haut niveau et de ne pas traiter les requêtes redondantes. En comparaison, c'est bien mieux que le serveur. raccroche directement. Par exemple, pendant Double Eleven, lorsque nous souhaitons passer une commande, nous verrons quelque chose comme "La demande est occupée, veuillez réessayer plus tard !".
Fusible : Je pense que tout le monde connaît le disjoncteur. Il équivaut à un interrupteur, qui peut empêcher la circulation lorsqu'il est ouvert. Par exemple, un fusible sautera lorsque le courant est trop important pour éviter d'endommager les composants.
Le disjoncteur de service signifie que l'appelant accède au service via un disjoncteur en tant que proxy. Le disjoncteur continuera à observer l'état de réussite et d'échec renvoyé par le service.
Lorsque la panne dépasse le seuil défini, le disjoncteur. est ouvert et la demande ne peut pas être authentifiée. Le service est accessible localement.
Scénarios d'utilisationLorsque le service échoue ou est mis à niveau, laissez le client échouer rapidement
La logique de traitement des échecs est facile à définir
) soient surchargées ou répondent lentement, les requêtes pour certaines interfaces et données non essentielles soient temporairement abandonnées en interne, et une
Sentinel est un projet open source d'Alibaba. Il fournit plusieurs dimensions telles que le contrôle de flux, la dégradation du disjoncteur et la protection de la charge du système pour garantir la stabilité des services.
Site officiel : github.com/alibaba/Sentinel/wiki
Sentinel est né à Alibaba en 2012, et son objectif principal est le contrôle du trafic. De 2013 à 2017, Sentinel s'est développé rapidement et est devenu un composant de base de tous les microservices Alibaba. Il est utilisé dans plus de 6 000 applications, couvrant presque tous les principaux scénarios de commerce électronique. En 2018, Sentinel est devenu un projet open source. En 2020, Sentinel Golang est sorti.
Caractéristiques :
Scénarios d'application riches : Sentinel a entrepris les scénarios de base de la promotion du trafic Double Eleven d'Alibaba au cours des 10 dernières années, tels que les ventes flash (c'est-à-dire que le trafic en rafale est contrôlé dans la plage que la capacité du système peut supporter) , messagerie Élimination des pics et remplissage des vallées, contrôle du flux des clusters, fusion en temps réel des applications indisponibles en aval, etc.
Surveillance complète en temps réel : Sentinel fournit également des fonctions de surveillance en temps réel. Vous pouvez voir les données de deuxième niveau d'une seule machine connectée à l'application dans la console, et même le résumé de l'état de fonctionnement d'un cluster de moins de 500 machines.
*Large Ecology*
Histoire de SentinelEn 2012, Sentinel est née, dont la fonction principale est le contrôle du débit d'entrée.
De 2013 à 2017, Sentinel s'est développé rapidement au sein du groupe Alibaba et est devenu un module technologique de base, couvrant tous les scénarios de base. Sentinel a ainsi accumulé un grand nombre de scénarios de consolidation de trafic et de pratiques de production.
En 2018, Sentinel était open source et continue d'évoluer.
Documentation officielle du site Web
Installation :go get github.com/alibaba/sentinel-golang/api
Go current limiting practice
qps current limiting
package main import ( "fmt" "log" sentinel "github.com/alibaba/sentinel-golang/api" "github.com/alibaba/sentinel-golang/core/base" "github.com/alibaba/sentinel-golang/core/flow" ) func main() { //基于sentinel的qps限流 //必须初始化 err := sentinel.InitDefault() if err != nil { log.Fatalf("Unexpected error: %+v", err) } //配置限流规则:1秒内通过10次 _, err = flow.LoadRules([]*flow.Rule{ { Resource: "some_test", TokenCalculateStrategy: flow.Direct, ControlBehavior: flow.Reject, //超过直接拒绝 Threshold: 10, //请求次数 StatIntervalInMs: 1000, //允许时间内 }, }) if err != nil { log.Fatalf("Unexpected error: %+v", err) return } for i := 0; i < 12; i++ { e, b := sentinel.Entry("some_test", sentinel.WithTrafficType(base.Inbound)) if b != nil { fmt.Println("限流了") } else { fmt.Println("检查通过") e.Exit() } } }
Imprimer les résultats :
检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 限流了 限流了
Thrnotting
package main import ( "fmt" "log" "time" sentinel "github.com/alibaba/sentinel-golang/api" "github.com/alibaba/sentinel-golang/core/base" "github.com/alibaba/sentinel-golang/core/flow" ) func main() { //基于sentinel的qps限流 //必须初始化 err := sentinel.InitDefault() if err != nil { log.Fatalf("Unexpected error: %+v", err) } //配置限流规则 _, err = flow.LoadRules([]*flow.Rule{ { Resource: "some_test", TokenCalculateStrategy: flow.Direct, ControlBehavior: flow.Throttling, //匀速通过 Threshold: 10, //请求次数 StatIntervalInMs: 1000, //允许时间内 }, }) if err != nil { log.Fatalf("Unexpected error: %+v", err) return } for i := 0; i < 12; i++ { e, b := sentinel.Entry("some_test", sentinel.WithTrafficType(base.Inbound)) if b != nil { fmt.Println("限流了") } else { fmt.Println("检查通过") e.Exit() } time.Sleep(time.Millisecond * 100) } }
检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过 检查通过
Warrm_up
package main import ( "fmt" "log" "math/rand" "time" sentinel "github.com/alibaba/sentinel-golang/api" "github.com/alibaba/sentinel-golang/core/base" "github.com/alibaba/sentinel-golang/core/flow" ) func main() { //先初始化sentinel err := sentinel.InitDefault() if err != nil { log.Fatalf("初始化sentinel 异常: %v", err) } var globalTotal int var passTotal int var blockTotal int ch := make(chan struct{}) //配置限流规则 _, err = flow.LoadRules([]*flow.Rule{ { Resource: "some-test", TokenCalculateStrategy: flow.WarmUp, //冷启动策略 ControlBehavior: flow.Reject, //直接拒绝 Threshold: 1000, WarmUpPeriodSec: 30, }, }) if err != nil { log.Fatalf("加载规则失败: %v", err) } //我会在每一秒统计一次,这一秒只能 你通过了多少,总共有多少, block了多少, 每一秒会产生很多的block for i := 0; i < 100; i++ { go func() { for { globalTotal++ e, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound)) if b != nil { //fmt.Println("限流了") blockTotal++ time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond) } else { 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 }
Résultat d'impression : atteint progressivement 1k, au Position 1k Fluctue de haut en bas
total:11, pass:9, block:0 total:21966, pass:488, block:21420 total:21793, pass:339, block:21414 total:21699, pass:390, block:21255 total:21104, pass:393, block:20654 total:21363, pass:453, block:20831 total:21619, pass:491, block:21052 total:21986, pass:533, block:21415 total:21789, pass:594, block:21123 total:21561, pass:685, block:20820 total:21663, pass:873, block:20717 total:20904, pass:988, block:19831 total:21500, pass:996, block:20423 total:21769, pass:1014, block:20682 total:20893, pass:1019, block:19837 total:21561, pass:973, block:20524 total:21601, pass:1014, block:20517 total:21475, pass:993, block:20420 total:21457, pass:983, block:20418 total:21397, pass:1024, block:20320 total:21690, pass:996, block:20641 total:21526, pass:991, block:20457 total:21779, pass:1036, block:20677
Allez au combat réel du disjoncteur
Ici, nous introduisons un numéro incorrect, visualisons le mécanisme détaillé du disjoncteur
error_count 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() 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=10s, recoveryTimeout=3s, maxErrorCount=50 { Resource: "abc", Strategy: circuitbreaker.ErrorCount, RetryTimeoutMs: 3000, //3s只有尝试回复 MinRequestAmount: 10, //静默数 StatIntervalMs: 5000, Threshold: 50, }, }) 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 { // g1 blocked totalBlock++ fmt.Println("协程熔断了") 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()%20+10) * time.Millisecond) e.Exit() } } }() go func() { for { total++ e, b := sentinel.Entry("abc") if b != nil { // g2 blocked totalBlock++ 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 }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!