ホームページ >バックエンド開発 >Golang >Go アプリケーションのサーキット ブレーカー

Go アプリケーションのサーキット ブレーカー

PHPz
PHPzオリジナル
2024-08-27 21:31:56715ブラウズ

最近では、特にマイクロサービス環境で作業している場合、アプリケーションが他のアプリケーションに依存することが非常に一般的です。アプリケーションがエラーを報告し始めることはよくあります。調査すると、パートナー チームまたはサプライヤーの一部の API がダウンしていることに気づきます。

アプリケーションの復元力を高めるための良い方法は、非推奨状態にあるアプリケーションとの通信を遮断することです。他の分野を観察しながら、電気工学からサーキットブレーカーの概念を吸収します。その中には機器、つまり回路ブレーカーが設置されており、障害が発生すると自動的にオフになります。これは私たちの家庭では非常に一般的で、電気網が不安定になり始めると自動的にオフになる回路ブレーカーが設置されています。

コンピューティングでは、中間状態も定義するため、サーキット ブレーカーはもう少し複雑です。以下の図は、サーキット ブレーカーがどのように機能するかをよりよく説明しています:

Circuit Breaker em aplicações Go

最後に、州は次のとおりです:

  • open: アプリケーション間で通信は行われません。この状態に達すると、リセット サービスの時間を確保するタイマーが開始されます。タイマーが終了すると、半開状態に移行します。
  • クローズ済み: アプリケーション間で通信が行われています。失敗したリクエストごとに、カウンターが更新されます。故障限界に達すると、回路がオープンに移行します。
  • ハーフオープン: 通信が完全に流れるまでの回復状態。その中で、成功カウンターはリクエストごとに更新されます。理想的な成功数に達した場合、回路はクローズドに移行します。リクエストが失敗した場合は、オープンに戻ります。

かなりクールですね?しかし、この概念をよりよく例示するために、実際にそれを行ってみてはどうでしょうか?

まず、サービス A を構築しましょう。サービス A はリクエストの受信を担当します。つまり、アプリケーションが依存するサービス、サプライヤーのサービスなどになります。簡単にするために、2 つのエンドポイント、常に 200 を返す /success と常に 500 を返す /failure を公開します。

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/success", func(w http.ResponseWriter, r *http.Request) { 
    w.WriteHeader(http.StatusOK) })
    http.HandleFunc("/failure", func(w http.ResponseWriter, r *http.Request) { 
    w.WriteHeader(http.StatusInternalServerError) })

    fmt.Println("Server is running at http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

サービス B はサービス A を呼び出す役割を果たします。これによりサーキット ブレーカーが構築されます。幸運なことに、Go コミュニティには、このパターンを実装する gobreak ライブラリがすでにあります。まず、ブレーカーのプロパティを定義します。

var st gobreaker.Settings
st.Name = "Circuit Breaker PoC"
st.Timeout = time.Second * 5
st.MaxRequests = 2
st.ReadyToTrip = func(counts gobreaker.Counts) bool {
    return counts.ConsecutiveFailures >= 1
}

ライブラリではさらに多くのことをカスタマイズできますが、次の 3 つに焦点を当てます。

  • タイムアウト: 回線が開いた状態を維持する時間。今回の場合、時間は 5 秒に設定されました。
  • MaxRequests: クローズされるまでに成功したリクエストの数。この例では、リクエストを 2 件に設定しています。
  • ReadyToTrip: クローズからオープンに移行する条件を定義します。わかりやすくするために、失敗は 1 回で十分だとしましょう。

その後、ブレーカーを初期化してリクエストを行うことができます。

cb := gobreaker.NewCircuitBreaker[int](st)

url := "http://localhost:8080/success"
cb.Execute(func() (int, error) { return Get(url) })
fmt.Println("Circuit Breaker state:", cb.State()) // closed!

url = "http://localhost:8080/failure"
cb.Execute(func() (int, error) { return Get(url) })
fmt.Println("Circuit Breaker state:", cb.State()) // open!

time.Sleep(time.Second * 6)
url = "http://localhost:8080/success"
cb.Execute(func() (int, error) { return Get(url) })
fmt.Println("Circuit Breaker state:", cb.State()) // half-open!

url = "http://localhost:8080/success"
cb.Execute(func() (int, error) { return Get(url) })
fmt.Println("Circuit Breaker state:", cb.State()) // closed!

gobreak が関数のラッパーとして機能することがわかります。関数がエラーを返した場合はエラーの数が増え、そうでない場合は成功の数が増えます。それでは、この関数を定義しましょう:

func Get(url string) (int, error) {
    r, _ := http.Get(url)

    if r.StatusCode != http.StatusOK {
        return r.StatusCode, fmt.Errorf("failed to get %s", url)
    }

    return r.StatusCode, nil
}

そして、サーキットブレーカーを使用した Go サービスがあります!このパターンを使用すると、サービスの復元力と耐障害性を高めることができます。ライブラリを使用すると、複雑さが完全に抽象化され、これを日常生活に組み込むプロセスが非常にシンプルになっていることがわかります。概念実証コード全体を確認したい場合は、ここにアクセスしてください。

他の回復力のパターンを知りたい場合は、Elton Minetto がこのトピックに関する素晴らしい投稿を公開しています!

この投稿についてどう思うかコメント欄で教えてください。質問があります: これまでにサーキットブレーカーを使用したことがありますか?ああ、私の個人ブログでも私を見つけることができます!

以上がGo アプリケーションのサーキット ブレーカーの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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