«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Автоматический выключатель в приложениях Go

Автоматический выключатель в приложениях Go

Опубликовано 12 сентября 2024 г.
Просматривать:519

В наши дни наше приложение часто зависит от других, особенно если мы работаем в среде микросервисов. Наше приложение довольно часто начинает сообщать об ошибках, и в ходе расследования мы замечаем, что некоторые API от партнерской команды или поставщика не работают.

Хорошей практикой для повышения устойчивости нашего приложения является прекращение связи с теми приложениями, которые находятся в устаревшем состоянии. Рассматривая другие области, мы впитываем понятие автоматического выключателя из электротехники. В нем размещается оборудование, или автоматический выключатель, который автоматически отключается при возникновении неисправности. Это очень распространено в наших домах, где есть автоматические выключатели, которые автоматически отключаются, если электрическая сеть начинает работать нестабильно.

В вычислениях наш автоматический выключатель немного сложнее, поскольку мы также определяем промежуточное состояние. Рисунок ниже лучше объясняет, как работает автоматический выключатель:

Circuit Breaker em aplicações Go

Наконец, состояния:

  • открыто: связь между приложениями отсутствует. При достижении этого состояния таймер начинает отводить время для услуги сброса. По окончании таймера мы переходим в полуоткрытое положение.
  • закрыто: связь между приложениями есть. Для каждого неудачного запроса счетчик обновляется. Если предел отказа достигнут, мы переводим цепь в разомкнутое состояние.
  • полуоткрытый: состояние восстановления до тех пор, пока связь не сможет осуществляться полностью. В нем счетчик успехов обновляется при каждом запросе. Если идеальное количество успехов достигнуто, мы переводим схему в замкнутое состояние. Если запросы терпят неудачу, мы возвращаемся к открытому.

Прикольно, правда? Но чтобы лучше проиллюстрировать концепцию, как насчет того, чтобы реализовать это на практике?

Для начала построим наш сервис А. Он будет отвечать за прием запросов, то есть это будет сервис, от которого зависит наше приложение, сервис поставщика и т. д. Чтобы упростить задачу, мы предоставим две конечные точки: /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
}

Хотя библиотека позволяет нам настраивать больше вещей, мы сосредоточимся на трех:

  • Тайм-аут: время, в течение которого схема будет оставаться в разомкнутом состоянии. В нашем случае время было установлено на 5 секунд.
  • MaxRequests: количество успешных запросов до закрытия. В нашем примере мы определяем это как 2 запроса.
  • ReadyToTrip: определяет условие перехода из закрытого состояния в открытое. Чтобы упростить задачу, скажем, достаточно одной неудачи.

Затем мы можем инициализировать прерыватель и делать запросы:

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, использующий автоматический выключатель! Используя этот шаблон, вы можете повысить отказоустойчивость и отказоустойчивость ваших сервисов. Мы можем заметить, что при использовании библиотеки сложность была полностью абстрагирована, что сделало процесс интеграции этого в нашу повседневную жизнь очень простым. Если вы хотите увидеть весь код, подтверждающий концепцию, просто зайдите сюда.

Если вам интересно узнать другие модели устойчивости, Элтон Минетто опубликовал отличный пост на эту тему!

Расскажите мне, что вы думаете об этом посте в комментариях, и вот вопрос: использовали ли вы когда-нибудь автоматические выключатели раньше? О, вы также можете найти меня в моем личном блоге!

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/mfbmina/circuit-breaker-em-aplicacoes-go-4hnn?1 Если есть какие-либо нарушения, свяжитесь с [email protected], чтобы удалить ее.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3