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

Go アプリのサーキット ブレーカー

Sep 03, 2024 pm 02:15 PM

今日、特にマイクロサービス環境で動作する場合、アプリケーションにいくつかの依存関係があることが一般的です。アプリがエラーを報告し、1 つの依存関係がダウンしていることが判明することは珍しくありません。

回復力を向上させるための良い習慣の 1 つは、正常に動作していないアプリとの通信をシャットダウンすることです。他の分野に目を向けると、故障が発生するとスイッチがオフになる回路ブレーカーの概念を電気工学から学びました。ブラジルでは、電力網が不安定になると自動的に停止するスイッチがすべての家にあります。

コンピューターサイエンスでは、サーキットブレーカーは中間状態も持つため、もう少し複雑です。以下の図は、その仕組みを詳しく説明しています:

Circuit Breaker in Go apps

簡単に言うと、考えられる状態は次のとおりです:

  • open: アプリ間の通信はありません。この状態に達すると、タイマーが開始され、依存関係が再確立されるようになります。タイマーが終了すると半開状態に移行します。
  • クローズ済み: アプリ間で通信が行われています。リクエストが失敗して完了するたびに、カウンターが更新されます。障害しきい値に達すると、回路がオープンに移行します。
  • 半開き:通常通りに仕事ができるようになるまでの治癒状態です。実行中に成功のしきい値に達すると、クローズに移行します。リクエストが失敗し続ける場合は、オープンに戻ります。

かなりクールですね?コンセプトをよりよく説明するには、コンセプトを作成してみてはいかがでしょうか?

まず、サービス A を構築しましょう。サービス A はすべてのリクエストを受信する責任を負います。つまり、メイン アプリが依存するサービスになります。簡略化するために、2 つのエンドポイントを公開します。1 つは常に 200 で応答する /success で、もう 1 つは常に 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 コミュニティには、パターンを実装した lib 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 がそれに関する素晴らしいブログ投稿を公開しています!

この記事や他の投稿は私の個人ブログでもご覧いただけます。このブログ投稿についてのご意見と 1 つの質問をコメント欄でお聞かせください。回路ブレーカーを使用したことがありますか?

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

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか? Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか? Mar 03, 2025 pm 05:17 PM

Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか?

Beegoフレームワークのページ間で短期情報転送を実装する方法は? Beegoフレームワークのページ間で短期情報転送を実装する方法は? Mar 03, 2025 pm 05:22 PM

Beegoフレームワークのページ間で短期情報転送を実装する方法は?

MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は? MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は? Mar 03, 2025 pm 05:18 PM

MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は?

GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか? GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか? Mar 10, 2025 pm 03:20 PM

GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか?

GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか? GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか? Mar 10, 2025 pm 05:38 PM

GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか?

Go言語でファイルを便利に書く方法は? Go言語でファイルを便利に書く方法は? Mar 03, 2025 pm 05:15 PM

Go言語でファイルを便利に書く方法は?

Goでユニットテストをどのように書きますか? Goでユニットテストをどのように書きますか? Mar 21, 2025 pm 06:34 PM

Goでユニットテストをどのように書きますか?

トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか? トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか? Mar 10, 2025 pm 05:36 PM

トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか?

See all articles