Heutzutage ist es durchaus üblich, dass unsere Anwendung von anderen abhängig ist, insbesondere wenn wir in einer Microservices-Umgebung arbeiten. Es kommt durchaus vor, dass unsere Anwendung Fehler meldet und wir bei der Untersuchung feststellen, dass eine API eines Partnerteams oder Lieferanten ausgefallen ist.
Eine gute Vorgehensweise zur Erhöhung der Ausfallsicherheit unserer Anwendung besteht darin, die Kommunikation mit Anwendungen zu unterbrechen, die sich in einem veralteten Zustand befinden. Bei der Betrachtung anderer Bereiche übernehmen wir das Konzept des Leistungsschalters aus der Elektrotechnik. Darin ist ein Gerät oder ein Leistungsschalter untergebracht, der sich bei einem Fehler automatisch abschaltet. Dies ist in unseren Häusern sehr häufig der Fall, denn dort gibt es Schutzschalter, die sich von selbst ausschalten, wenn das Stromnetz instabil wird.
In der Informatik ist unser Circuit Breaker etwas komplexer, da wir auch einen Zwischenzustand definieren. Die folgende Zeichnung erklärt besser, wie ein Leistungsschalter funktioniert:
Schließlich sind die Zustände:
Ziemlich cool, oder? Aber um das Konzept besser zu veranschaulichen, wie wäre es, wenn wir es in die Praxis umsetzen?
Zuerst bauen wir unseren Dienst A auf. Er ist für den Empfang von Anfragen verantwortlich, d. h. es handelt sich um den Dienst, von dem unsere Anwendung abhängt, den Dienst des Lieferanten usw. Zur Vereinfachung stellen wir zwei Endpunkte bereit, einen /success, der immer 200 zurückgibt, und einen /failure, der immer 500 zurückgibt.
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)) }
Service B wird für den Anruf von Service A verantwortlich sein. Er wird unseren Leistungsschalter bauen. Zum Glück verfügt die Go-Community bereits über die Gobreaker-Bibliothek, die das Muster implementiert! Zuerst definieren wir die Eigenschaften unseres Leistungsschalters:
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 }
Obwohl uns die Bibliothek die Anpassung weiterer Dinge ermöglicht, konzentrieren wir uns auf drei:
Dann können wir den Breaker initialisieren und Anfragen stellen:
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!
Wir können feststellen, dass Gobreaker als Wrapper um eine Funktion fungiert. Wenn die Funktion einen Fehler zurückgibt, erhöht sie die Anzahl der Fehler, andernfalls erhöht sie die Anzahl der Erfolge. Definieren wir also diese Funktion:
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 }
Und wir haben unseren Go-Service mit einem Leistungsschalter! Durch die Verwendung dieses Musters können Sie die Ausfallsicherheit und Fehlertoleranz Ihrer Dienste erhöhen. Wir können feststellen, dass bei der Nutzung der Bibliothek die Komplexität vollständig abstrahiert wurde, was den Prozess der Integration in unser tägliches Leben sehr einfach macht. Wenn Sie den gesamten Proof-of-Concept-Code sehen möchten, klicken Sie einfach hier.
Wenn Sie neugierig sind, andere Resilienzmuster kennenzulernen, hat Elton Minetto einen tollen Beitrag zu diesem Thema veröffentlicht!
Sagen Sie mir in den Kommentaren, was Sie von diesem Beitrag halten, und hier ist eine Frage: Haben Sie schon einmal Leistungsschalter verwendet? Oh, Sie können mich auch auf meinem persönlichen Blog finden!
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3