「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > Go アプリケーションのサーキット ブレーカー

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

2024 年 11 月 7 日に公開
ブラウズ:102

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

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

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

Circuit Breaker em aplicações Go

最終的に州は次のとおりです:

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

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

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

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 がこのトピックに関する素晴らしい投稿を公開しています!

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

リリースステートメント この記事は次の場所に転載されています: https://dev.to/mfbmina/circuit-breaker-em-aplicacoes-go-4hnn?1 侵害がある場合は、[email protected] に連絡して削除してください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3