最近では、特にマイクロサービス環境で作業している場合、アプリケーションが他のアプリケーションに依存することが非常に一般的です。アプリケーションがエラーを報告し始めることはよくあります。調査すると、パートナー チームまたはサプライヤーの一部の API がダウンしていることに気づきます。
アプリケーションの復元力を高めるための良い方法は、非推奨状態にあるアプリケーションとの通信を遮断することです。他の分野を観察しながら、電気工学からサーキットブレーカーの概念を吸収します。その中には、故障が発生した場合に自動的に電源が切れる機器、つまりブレーカーが設置されています。これは私たちの家庭ではよくあることですが、電気ネットワークが不安定になり始めると自動的にオフになる回路ブレーカーが設置されています。
コンピューティングでは、中間状態も定義するため、サーキット ブレーカーは少し複雑になります。以下の図は、サーキット ブレーカーがどのように機能するかをよりよく説明しています:
最終的に州は次のとおりです:
かなりクールですね?しかし、この概念をよりよく例示するために、実際にそれを行ってみてはどうでしょうか?
まず、サービス 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 つに焦点を当てます。
その後、ブレーカーを初期化してリクエストを行うことができます:
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 がこのトピックに関する素晴らしい投稿を公開しています!
この投稿についてどう思うかコメント欄で教えてください。質問があります。サーキットブレーカーを使用したことがありますか?ああ、私の個人ブログでも私を見つけることができます!
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3