This commit is contained in:
Kevin Wan 2021-08-04 18:45:05 +08:00 committed by GitHub
parent 16cc990fdd
commit 0ee7654407
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 1 deletions

View File

@ -69,8 +69,8 @@ func (c *client) buildDialOptions(opts ...ClientOption) []grpc.DialOption {
WithUnaryClientInterceptors(
clientinterceptors.TracingInterceptor,
clientinterceptors.DurationInterceptor,
clientinterceptors.BreakerInterceptor,
clientinterceptors.PrometheusInterceptor,
clientinterceptors.BreakerInterceptor,
clientinterceptors.TimeoutInterceptor(cliOpts.Timeout),
),
}

View File

@ -1,6 +1,8 @@
package codes
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -10,6 +12,17 @@ func Acceptable(err error) bool {
switch status.Code(err) {
case codes.DeadlineExceeded, codes.Internal, codes.Unavailable, codes.DataLoss:
return false
case codes.Unknown:
return acceptableUnknown(err)
default:
return true
}
}
func acceptableUnknown(err error) bool {
switch err {
case context.DeadlineExceeded:
return false
default:
return true
}

View File

@ -58,10 +58,12 @@ func (s *rpcServer) Start(register RegisterFn) error {
serverinterceptors.UnaryCrashInterceptor(),
serverinterceptors.UnaryStatInterceptor(s.metrics),
serverinterceptors.UnaryPrometheusInterceptor(),
serverinterceptors.UnaryBreakerInterceptor(),
}
unaryInterceptors = append(unaryInterceptors, s.unaryInterceptors...)
streamInterceptors := []grpc.StreamServerInterceptor{
serverinterceptors.StreamCrashInterceptor,
serverinterceptors.StreamBreakerInterceptor,
}
streamInterceptors = append(streamInterceptors, s.streamInterceptors...)
options := append(s.options, WithUnaryServerInterceptors(unaryInterceptors...),

View File

@ -0,0 +1,33 @@
package serverinterceptors
import (
"context"
"github.com/tal-tech/go-zero/core/breaker"
"github.com/tal-tech/go-zero/zrpc/internal/codes"
"google.golang.org/grpc"
)
// StreamBreakerInterceptor is an interceptor that acts as a circuit breaker.
func StreamBreakerInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo,
handler grpc.StreamHandler) (err error) {
breakerName := info.FullMethod
return breaker.DoWithAcceptable(breakerName, func() error {
return handler(srv, stream)
}, codes.Acceptable)
}
// UnaryBreakerInterceptor is an interceptor that acts as a circuit breaker.
func UnaryBreakerInterceptor() grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler) (resp interface{}, err error) {
breakerName := info.FullMethod
err = breaker.DoWithAcceptable(breakerName, func() error {
var err error
resp, err = handler(ctx, req)
return err
}, codes.Acceptable)
return resp, err
}
}

View File

@ -0,0 +1,31 @@
package serverinterceptors
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestStreamBreakerInterceptor(t *testing.T) {
err := StreamBreakerInterceptor(nil, nil, &grpc.StreamServerInfo{
FullMethod: "any",
}, func(
srv interface{}, stream grpc.ServerStream) error {
return status.New(codes.DeadlineExceeded, "any").Err()
})
assert.NotNil(t, err)
}
func TestUnaryBreakerInterceptor(t *testing.T) {
interceptor := UnaryBreakerInterceptor()
_, err := interceptor(nil, nil, &grpc.UnaryServerInfo{
FullMethod: "any",
}, func(ctx context.Context, req interface{}) (interface{}, error) {
return nil, status.New(codes.DeadlineExceeded, "any").Err()
})
assert.NotNil(t, err)
}