„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Leistungsschalter in Go-Anwendungen

Leistungsschalter in Go-Anwendungen

Veröffentlicht am 12.09.2024
Durchsuche:868

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:

Circuit Breaker em aplicações Go

Schließlich sind die Zustände:

  • offen: Es findet keine Kommunikation zwischen Anwendungen statt. Bei Erreichen dieses Zustands startet ein Timer, um Zeit für den Rücksetzdienst einzuräumen. Am Ende des Timers gehen wir in den halboffenen Zustand über.
  • geschlossen: Es findet Kommunikation zwischen Anwendungen statt. Für jede fehlgeschlagene Anfrage wird ein Zähler aktualisiert. Wenn die Fehlergrenze erreicht ist, schalten wir den Stromkreis auf „Offen“.
  • halboffen: Erholungszustand, bis die Kommunikation vollständig fließen kann. Darin wird bei jeder Anfrage ein Erfolgszähler aktualisiert. Wenn die ideale Erfolgszahl erreicht ist, stellen wir den Kreislauf auf geschlossen. Wenn Anfragen fehlschlagen, wechseln wir zurück zum Öffnen.

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:

  • Timeout: Die Zeit, die der Stromkreis im offenen Zustand bleibt. In unserem Fall wurde die Zeit auf 5 Sekunden eingestellt.
  • MaxRequests: Anzahl erfolgreicher Anfragen, bevor sie geschlossen werden. In unserem Beispiel definieren wir es als 2 Anfragen.
  • ReadyToTrip: Definiert die Bedingung für den Übergang von geschlossen nach offen. Nehmen wir zur Vereinfachung an, ein Fehler reicht aus.

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!

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/mfbmina/Circuit-breaker-em-aplicacoes-go-4hnn?1 Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen
Neuestes Tutorial Mehr>

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