[Go] gobreaker
sony์์ ๋ง๋ ์ํท๋ธ๋ ์ด์ปค ๊ตฌํ์ฒด๋ค. ์๊ธฐ๋ค์ด ์ฐ๋ ค๊ณ ๋ง๋ ๊ฑฐ๊ฐ๋ค.
์ ์์ ์ธ ์ํท๋ธ๋ ์ด์ปค ํจํด์ ๋ฐ๋ฅธ๋ค.
https://blog.naver.com/sssang97/222890127728
์ค์น
์ค์น๋ ๊ฐ๋จํ๋ค. ๋ํ๋์๋ ๋ณ๊ฑฐ์๋ค.
go get github.com/sony/gobreaker

๊ธฐ๋ณธ๊ตฌ์ฑ
์ ์ญ๋ณ์๋ ์ ์ญ์ ๊ฐ๊น์ด ๋ผ์ดํํ์์ ๊ฐ์ง ๋ณ์๋ก ์ํท๋ธ๋ ์ด๊ฑฐ ๋ณ์๋ฅผ ๋๋ค.
๊ทธ๋ฆฌ๊ณ Setting ๊ฐ์ฒด๋ฅผ ํตํด ์ค์ ๊ฐ๋ค์ ๋ฃ๊ณ ์ํท๋ธ๋ ์ด์ปค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
์ธํ ์๋ ์ด๋ฐ ๊ฐ๋ค์ด ์๋ค.

- Name์ ๋ฉํ๋ฐ์ดํฐ์ฑ ์ด๋ฆ์ด๊ณ .
- MaxRequets๋ half-open ์ํ์ผ๋ ํ๋ฒ์ ๋ค์ด์ฌ ์ ์๋ ์์ฒญ ์๋ค.
- Interval์ close ์ํ์์ ๋ด๋ถ ์นด์ดํธ๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ํ ์ฃผ๊ธฐ๋ค. 0์ด๋ฉด ์ด๊ธฐํํ์ง ์๋๋ค.
- Timeout์ ๋ง ๊ทธ๋๋ก ํ์์์ ์ค์ ์ด๋ค. ํด๋น ์ด๊ฐ ์ง๋๋ฉด half-open ์ํ๊ฐ ๋๋ค. 0์ด๋ฉด 60์ด๋ค.
- ReadyToTrip์ close ์ํ๋ก ์ง์ ํ๊ธฐ ์ํ ์กฐ๊ฑด์ด๋ค. ์ ๋ฐํ๊ฐ์ด true๊ฐ ๋๋ฉด close๊ฐ ๋๋ค.
- OnStateChange๋ ๊ทธ๋ฅ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํธ์ถ๋๋ค.
- IsSuccessful๋ ์ฑ๊ณต ์กฐ๊ฑด์ ์ง์ ํ๋ค. error๊ฐ ๋ฐํ๋ ๋ ํน์ ์ค๋ฅ๋ง ์ฑ๊ณต์ผ๋ก ๊ฐ์ฃผํด์ผ ํ๊ฑฐ๋ ์ฌ์ฉํ๋ฉด ๋๋ค.
์๋๋ ์ํท๋ธ๋ ์ด์ปค ๊ธฐ๋ฐ์ผ๋ก Get ์์ฒญ์ ๋ ๋ฆฌ๋ ํจ์๋ฅผ ๊ตฌํํ ์๋ค.
๋ณ๊ฑด ์๋ค. Execute๋ก ๊ฐ์ธ์ ์คํํ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
์ ๋ด๋ถ ํจ์์์ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ฉด ๊ทธ๊ฒ ReadyToTrip์ผ๋ก ๊ฒ์ฌํด์ close ์ํ๋ก ์ง์
ํ๊ณ , ๊ทธ๋ฐ ์์ผ๋ก ์ ์ด๊ฐ ๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ฉด ๊ทธ๋ฅ ์ฐ๋ฉด ๋๋ค.
์๋๋ ์ ์ฒด ์์ ์ฝ๋๋ค.
package main
import (
"fmt"
"io"
"log"
"net/http"
"github.com/sony/gobreaker"
)
var circuitBreaker *gobreaker.CircuitBreaker
func init() {
var setting gobreaker.Settings
setting.Name = "HTTP GET ํ
์คํธ"
setting.ReadyToTrip = func(counts gobreaker.Counts) bool {
// 3๋ฒ ์ด์ ํธ์ถ๋๊ณ , 60% ์ด์ ์คํจํ๋ฉด circuit breaker๊ฐ ์ด๋ฆฐ๋ค.
failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
return counts.Requests >= 3 && failureRatio >= 0.6
}
circuitBreaker = gobreaker.NewCircuitBreaker(setting)
}
// Get wraps http.Get in CircuitBreaker.
func Get(url string) ([]byte, error) {
// ์ํท๋ธ๋ ์ด์ปค๋ฅผ ํตํด ํธ์ถํ๋ค.
body, err := circuitBreaker.Execute(func() (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
})
if err != nil {
return nil, err
}
return body.([]byte), nil
}
func main() {
body, err := Get("http://www.google.com/robots.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}