From cb5f12c7ff78a7d4246820f4792c65fe518bf8fa Mon Sep 17 00:00:00 2001 From: pinbor Date: Mon, 20 Nov 2023 15:24:19 +0800 Subject: [PATCH] =?UTF-8?q?=E7=86=94=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- circuitbreaker/gobreaker.go | 15 +++++++++++++++ go.mod | 2 ++ go.sum | 7 +++++++ option.go | 7 +++++++ server.go | 11 ++++++++--- 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 circuitbreaker/gobreaker.go diff --git a/README.md b/README.md index c0e7446..9561427 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ go get -u github.com/go-water/water + errors 自定义处理 + pool 管理请求参数 + option 配置修改 -+ rate limit ++ rate limit(限流) ++ circuit breaker(熔断) ### 样例仓库 + [https://github.com/go-water/go-water](https://github.com/go-water/go-water) diff --git a/circuitbreaker/gobreaker.go b/circuitbreaker/gobreaker.go new file mode 100644 index 0000000..83712f8 --- /dev/null +++ b/circuitbreaker/gobreaker.go @@ -0,0 +1,15 @@ +package circuitbreaker + +import ( + "context" + "github.com/go-water/water/endpoint" + "github.com/sony/gobreaker" +) + +func GoBreaker(cb *gobreaker.CircuitBreaker) endpoint.Middleware { + return func(next endpoint.Endpoint) endpoint.Endpoint { + return func(ctx context.Context, request any) (any, error) { + return cb.Execute(func() (any, error) { return next(ctx, request) }) + } + } +} diff --git a/go.mod b/go.mod index fd8624f..81b0ede 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,10 @@ go 1.21 require ( github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/sony/gobreaker v0.5.0 github.com/spf13/viper v1.17.0 go.uber.org/zap v1.26.0 + golang.org/x/time v0.4.0 ) require ( diff --git a/go.sum b/go.sum index c04c0a6..440467f 100644 --- a/go.sum +++ b/go.sum @@ -157,6 +157,8 @@ github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9c github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= +github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= @@ -170,6 +172,7 @@ github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -340,6 +343,10 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= +golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/option.go b/option.go index 34b932d..2832bc7 100644 --- a/option.go +++ b/option.go @@ -2,6 +2,7 @@ package water import ( "context" + "github.com/sony/gobreaker" "golang.org/x/time/rate" "time" ) @@ -23,3 +24,9 @@ func ServerLimiter(interval time.Duration, b int) ServerOption { s.limit = rate.NewLimiter(rate.Every(interval), b) } } + +func ServerBreaker(breaker *gobreaker.CircuitBreaker) ServerOption { + return func(s *Server) { + s.breaker = breaker + } +} diff --git a/server.go b/server.go index 3d1e144..dda0e62 100644 --- a/server.go +++ b/server.go @@ -2,8 +2,10 @@ package water import ( "context" + "github.com/go-water/water/circuitbreaker" "github.com/go-water/water/endpoint" "github.com/go-water/water/ratelimit" + "github.com/sony/gobreaker" "go.uber.org/zap" "golang.org/x/time/rate" ) @@ -19,6 +21,7 @@ type Server struct { errorHandler ErrorHandler l *zap.Logger limit *rate.Limiter + breaker *gobreaker.CircuitBreaker } func NewHandler(srv Service, options ...ServerOption) Handler { @@ -27,10 +30,12 @@ func NewHandler(srv Service, options ...ServerOption) Handler { option(s) } + s.e = srv.Endpoint() if s.limit != nil { - s.e = ratelimit.NewErrorLimiter(s.limit)(srv.Endpoint()) - } else { - s.e = srv.Endpoint() + s.e = ratelimit.NewErrorLimiter(s.limit)(s.e) + } + if s.breaker != nil { + s.e = circuitbreaker.GoBreaker(s.breaker)(s.e) } handler := NewLogErrorHandler(log, srv.Name(srv))