今日、特にマイクロサービス環境で動作する場合、アプリケーションにいくつかの依存関係があることが一般的です。アプリがエラーを報告し、1 つの依存関係がダウンしていることが判明することは珍しくありません。
回復力を向上させるための良い習慣の 1 つは、正常に動作していないアプリとの通信をシャットダウンすることです。他の分野に目を向けると、故障が発生するとスイッチがオフになる回路ブレーカーの概念を電気工学から学びました。ブラジルでは、電力網が不安定になると自動的に停止するスイッチがすべての家にあります。
コンピューターサイエンスでは、サーキットブレーカーは中間状態も持つため、もう少し複雑です。以下の図は、その仕組みを詳しく説明しています:
簡単に言うと、考えられる状態は次のとおりです:
かなりクールですね?コンセプトをよりよく説明するには、コンセプトを作成してみてはいかがでしょうか?
まず、サービス 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 つのみに焦点を当てます。
ここで、ブレーカーを初期化してリクエストを送信します。
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 サイトの他の関連記事を参照してください。