ホームページ  >  記事  >  バックエンド開発  >  コンテキストを使用して Go でリクエスト サーキット ブレーカーを実装する方法

コンテキストを使用して Go でリクエスト サーキット ブレーカーを実装する方法

WBOY
WBOYオリジナル
2023-07-25 09:04:541389ブラウズ

コンテキストを使用して Go でリクエスト サーキット ブレーカーを実装する方法

マイクロサービス アーキテクチャの普及により、さまざまなサービス間の通信がますます頻繁になってきました。サービス間通信では、呼び出しチェーンが非常に長くなる可能性があり、1 つのリクエストの失敗またはタイムアウトによって呼び出しチェーン全体が失敗し、システム全体の可用性に影響を与える可能性があります。単一サービスの障害からシステム全体を保護するために、リクエスト サーキット ブレークを使用して、特定のサービスへのアクセスを制御および制限できます。この記事では、コンテキストを使用して Go でリクエスト サーキット ブレーカーを実装する方法を紹介します。

リクエストサーキットブレーカーとは何ですか?

リクエストサーキットブレークは、システム全体を保護するために使用される戦略です。サービスのリクエスト失敗率が所定のしきい値を超えると、リクエスト サーキット ブレーカーはサービスへのアクセスを即座に拒否し、連鎖的な失敗の発生を回避します。リクエスト ブレーカー モードは、通常、サーキット ブレーカー モード (サーキット ブレーカー パターン) と組み合わせて使用​​され、リクエストが失敗した場合にサーキット ブレーカーがすぐにオープンされるため、サービスへのリクエストが拒否され、大量のリクエストが蓄積してサービスが中断されるのを防ぎます。システムリソースの枯渇を引き起こします。

コンテキストを使用して Go でリクエスト サーキット ブレーカーを実装するサンプル コードは次のとおりです。

package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

type CircuitBreaker struct {
    context    context.Context
    cancel     context.CancelFunc
    maxFail    int
    fail       int
    breaker    bool
    resetTime  time.Duration
    breakerMux sync.Mutex
}

func NewCircuitBreaker(maxFail int, resetTime time.Duration) *CircuitBreaker {
    ctx, cancel := context.WithCancel(context.Background())

    circuitBreaker := &CircuitBreaker{
        context:    ctx,
        cancel:     cancel,
        maxFail:    maxFail,
        fail:       0,
        breaker:    false,
        resetTime:  resetTime,
        breakerMux: sync.Mutex{},
    }

    return circuitBreaker
}

func (c *CircuitBreaker) Do(req func() error) error {
    select {
    case <-c.context.Done():
        return fmt.Errorf("circuit breaker is open")
    default:
        if !c.breaker {
            err := req()
            if err == nil {
                c.reset()
            } else {
                c.fail++
                if c.fail >= c.maxFail {
                    c.breakerMux.Lock()
                    c.breaker = true
                    c.breakerMux.Unlock()
                    go time.AfterFunc(c.resetTime, c.reset)
                }
            }
            return err
        } else {
            return fmt.Errorf("circuit breaker is open") 
        }
    }
}

func (c *CircuitBreaker) reset() {
    c.fail = 0
    c.breakerMux.Lock()
    c.breaker = false
    c.breakerMux.Unlock()
    c.cancel()
}

func main() {
    circuitBreaker := NewCircuitBreaker(3, 2*time.Minute)

    // 进行模拟请求
    for i := 0; i < 10; i++ {
        err := circuitBreaker.Do(func() error {
            // 这里执行实际的请求操作,此处只是模拟
            fmt.Println("执行请求...")
            if i%5 == 0 {
                return fmt.Errorf("request failed")
            }
            return nil
        })

        if err != nil {
            fmt.Printf("请求失败: %v
", err)
        } else {
            fmt.Println("请求成功")
        }
    }
}

上記のサンプル コードでは、CircuitBreaker 構造体を通じて単純なリクエスト サーキット ブレーカーを実装しました。 CircuitBreaker 構造体には次の属性があります:

  • context および cancel: リクエスト ブレーカーのライフ サイクルを制御するために使用され、ヒューズが開いた後、リクエストは拒否されます。
  • maxFail: 最大失敗回数を設定し、設定値を超えるとヒューズが切れます。
  • fail: 失敗したリクエストの数を記録します。
  • ブレーカー: ヒューズのステータスを記録します。true の場合、ヒューズが開いていることを意味します。
  • resetTime: ヒューズのリセット時間ヒューズを開いた後、この時間が経過すると、ヒューズは再び閉じられます。

特定のリクエスト操作は Do メソッドを通じて実行できます。リクエストが成功すると、失敗カウントはリセットされ、nil が返されます。要求が失敗すると失敗回数が増加し、失敗回数が設定値に達するとヒューズが開きます。
ヒューズが開くと、新しいリクエストはすぐにエラー情報を返すことに注意してください。

メイン関数では、サンプルの CircuitBreaker を作成し、10 個のリクエストをシミュレートしました。失敗の数が設定値に達すると、ヒューズが開き、新しいリクエストは拒否されます。

コンテキスト パッケージとカスタム CircuitBreaker 構造を使用することで、Go でリクエスト ブレーカー関数を簡単に実装できます。リクエスト サーキット ブレーカーを使用すると、単一のサービス障害の影響からシステム全体を効果的に保護し、システムの可用性と安定性を向上させることができます。

以上がコンテキストを使用して Go でリクエスト サーキット ブレーカーを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。