В наши дни наше приложение часто зависит от других, особенно если мы работаем в среде микросервисов. Наше приложение довольно часто начинает сообщать об ошибках, и в ходе расследования мы замечаем, что некоторые API от партнерской команды или поставщика не работают.
Хорошей практикой для повышения устойчивости нашего приложения является прекращение связи с теми приложениями, которые находятся в устаревшем состоянии. Рассматривая другие области, мы впитываем понятие автоматического выключателя из электротехники. В нем размещается оборудование, или автоматический выключатель, который автоматически отключается при возникновении неисправности. Это очень распространено в наших домах, где есть автоматические выключатели, которые автоматически отключаются, если электрическая сеть начинает работать нестабильно.
В вычислениях наш автоматический выключатель немного сложнее, поскольку мы также определяем промежуточное состояние. Рисунок ниже лучше объясняет, как работает автоматический выключатель:
Наконец, состояния:
Прикольно, правда? Но чтобы лучше проиллюстрировать концепцию, как насчет того, чтобы реализовать это на практике?
Для начала построим наш сервис А. Он будет отвечать за прием запросов, то есть это будет сервис, от которого зависит наше приложение, сервис поставщика и т. д. Чтобы упростить задачу, мы предоставим две конечные точки: /success, которая всегда будет возвращать 200, и /failure, которая всегда будет возвращать 500.
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 уже есть библиотека gobreaker, реализующая этот шаблон! Сначала мы определяем свойства нашего прерывателя:
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 }
Хотя библиотека позволяет нам настраивать больше вещей, мы сосредоточимся на трех:
Затем мы можем инициализировать прерыватель и делать запросы:
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!
Мы можем заметить, что gobreaker работает как оболочка функции. Если функция возвращает ошибку, она увеличивает количество ошибок, если нет — увеличивает количество успехов. Итак, давайте определим эту функцию:
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, использующий автоматический выключатель! Используя этот шаблон, вы можете повысить отказоустойчивость и отказоустойчивость ваших сервисов. Мы можем заметить, что при использовании библиотеки сложность была полностью абстрагирована, что сделало процесс интеграции этого в нашу повседневную жизнь очень простым. Если вы хотите увидеть весь код, подтверждающий концепцию, просто зайдите сюда.
Если вам интересно узнать другие модели устойчивости, Элтон Минетто опубликовал отличный пост на эту тему!
Расскажите мне, что вы думаете об этом посте в комментариях, и вот вопрос: использовали ли вы когда-нибудь автоматические выключатели раньше? О, вы также можете найти меня в моем личном блоге!
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3