packagemainimport("context""flag""log""time"pb"github.com/lixd/grpc-go-example/features/proto/echo""google.golang.org/grpc")var(addr=flag.String("addr","localhost:50052","the address to connect to")// 更多配置信息查看官方文档: https://github.com/grpc/grpc/blob/master/doc/service_config.md// service这里语法为<package>.<service> package就是proto文件中指定的package,service也是proto文件中指定的 Service Name。// method 可以不指定 即当前service下的所以方法都使用该配置。retryPolicy=`{
"methodConfig": [{
"name": [{"service": "echo.Echo","method":"UnaryEcho"}],
"retryPolicy": {
"MaxAttempts": 4,
"InitialBackoff": ".01s",
"MaxBackoff": ".01s",
"BackoffMultiplier": 1.0,
"RetryableStatusCodes": [ "UNAVAILABLE" ]
}
}]}`)funcmain(){flag.Parse()conn,err:=grpc.Dial(*addr,grpc.WithInsecure(),grpc.WithDefaultServiceConfig(retryPolicy))iferr!=nil{log.Fatalf("did not connect: %v",err)}deferfunc(){ife:=conn.Close();e!=nil{log.Printf("failed to close connection: %s",e)}}()c:=pb.NewEchoClient(conn)ctx,cancel:=context.WithTimeout(context.Background(),1*time.Second)defercancel()reply,err:=c.UnaryEcho(ctx,&pb.EchoRequest{Message:"Try and Success"})iferr!=nil{log.Fatalf("UnaryEcho error: %v",err)}log.Printf("UnaryEcho reply: %v",reply)}
配置信息具体含义这里先不解释,在后续章节有详细说明。
Run
先启动服务端
1
2
3
lixd@17x:~/17x/projects/grpc-go-example/features/retry/server$ go run main.go
listen on address :50052
2021/02/17 17:35:29 request failed count: 1
在启动客户端
1
2
3
lixd@17x:~/17x/projects/grpc-go-example/features/retry/client$ go run main.go
2021/02/17 17:35:29 UnaryEcho error: rpc error: code= Unavailable desc= maybeFailRequest: failing it
exit status 1
// Configuration for a method.
messageMethodConfig{// The names of the methods to which this configuration applies.
// - MethodConfig without names (empty list) will be skipped.
// - Each name entry must be unique across the entire ServiceConfig.
// - If the 'method' field is empty, this MethodConfig specifies the defaults
// for all methods for the specified service.
// - If the 'service' field is empty, the 'method' field must be empty, and
// this MethodConfig specifies the default for all methods (it's the default
// config).
//
// When determining which MethodConfig to use for a given RPC, the most
// specific match wins. For example, let's say that the service config
// contains the following MethodConfig entries:
//
// method_config { name { } ... }
// method_config { name { service: "MyService" } ... }
// method_config { name { service: "MyService" method: "Foo" } ... }
//
// MyService/Foo will use the third entry, because it exactly matches the
// service and method name. MyService/Bar will use the second entry, because
// it provides the default for all methods of MyService. AnotherService/Baz
// will use the first entry, because it doesn't match the other two.
//
// In JSON representation, value "", value `null`, and not present are the
// same. The following are the same Name:
// - { "service": "s" }
// - { "service": "s", "method": null }
// - { "service": "s", "method": "" }
messageName{stringservice=1;// Required. Includes proto package name.
stringmethod=2;}repeatedNamename=1;// Whether RPCs sent to this method should wait until the connection is
// ready by default. If false, the RPC will abort immediately if there is
// a transient failure connecting to the server. Otherwise, gRPC will
// attempt to connect until the deadline is exceeded.
//
// The value specified via the gRPC client API will override the value
// set here. However, note that setting the value in the client API will
// also affect transient errors encountered during name resolution, which
// cannot be caught by the value here, since the service config is
// obtained by the gRPC client via name resolution.
google.protobuf.BoolValuewait_for_ready=2;// The default timeout in seconds for RPCs sent to this method. This can be
// overridden in code. If no reply is received in the specified amount of
// time, the request is aborted and a DEADLINE_EXCEEDED error status
// is returned to the caller.
//
// The actual deadline used will be the minimum of the value specified here
// and the value set by the application via the gRPC client API. If either
// one is not set, then the other will be used. If neither is set, then the
// request has no deadline.
google.protobuf.Durationtimeout=3;// The maximum allowed payload size for an individual request or object in a
// stream (client->server) in bytes. The size which is measured is the
// serialized payload after per-message compression (but before stream
// compression) in bytes. This applies both to streaming and non-streaming
// requests.
//
// The actual value used is the minimum of the value specified here and the
// value set by the application via the gRPC client API. If either one is
// not set, then the other will be used. If neither is set, then the
// built-in default is used.
//
// If a client attempts to send an object larger than this value, it will not
// be sent and the client will see a ClientError.
// Note that 0 is a valid value, meaning that the request message
// must be empty.
google.protobuf.UInt32Valuemax_request_message_bytes=4;// The maximum allowed payload size for an individual response or object in a
// stream (server->client) in bytes. The size which is measured is the
// serialized payload after per-message compression (but before stream
// compression) in bytes. This applies both to streaming and non-streaming
// requests.
//
// The actual value used is the minimum of the value specified here and the
// value set by the application via the gRPC client API. If either one is
// not set, then the other will be used. If neither is set, then the
// built-in default is used.
//
// If a server attempts to send an object larger than this value, it will not
// be sent, and a ServerError will be sent to the client instead.
// Note that 0 is a valid value, meaning that the response message
// must be empty.
google.protobuf.UInt32Valuemax_response_message_bytes=5;// The retry policy for outgoing RPCs.
messageRetryPolicy{// The maximum number of RPC attempts, including the original attempt.
//
// This field is required and must be greater than 1.
// Any value greater than 5 will be treated as if it were 5.
uint32max_attempts=1;// Exponential backoff parameters. The initial retry attempt will occur at
// random(0, initial_backoff). In general, the nth attempt will occur at
// random(0,
// min(initial_backoff*backoff_multiplier**(n-1), max_backoff)).
// Required. Must be greater than zero.
google.protobuf.Durationinitial_backoff=2;// Required. Must be greater than zero.
google.protobuf.Durationmax_backoff=3;floatbackoff_multiplier=4;// Required. Must be greater than zero.
// The set of status codes which may be retried.
//
// This field is required and must be non-empty.
repeatedgoogle.rpc.Coderetryable_status_codes=5;}// The hedging policy for outgoing RPCs. Hedged RPCs may execute more than
// once on the server, so only idempotent methods should specify a hedging
// policy.
messageHedgingPolicy{// The hedging policy will send up to max_requests RPCs.
// This number represents the total number of all attempts, including
// the original attempt.
//
// This field is required and must be greater than 1.
// Any value greater than 5 will be treated as if it were 5.
uint32max_attempts=1;// The first RPC will be sent immediately, but the max_requests-1 subsequent
// hedged RPCs will be sent at intervals of every hedging_delay. Set this
// to 0 to immediately send all max_requests RPCs.
google.protobuf.Durationhedging_delay=2;// The set of status codes which indicate other hedged RPCs may still
// succeed. If a non-fatal status code is returned by the server, hedged
// RPCs will continue. Otherwise, outstanding requests will be canceled and
// the error returned to the client application layer.
//
// This field is optional.
repeatedgoogle.rpc.Codenon_fatal_status_codes=3;}// Only one of retry_policy or hedging_policy may be set. If neither is set,
// RPCs will not be retried or hedged.
oneofretry_or_hedging_policy{RetryPolicyretry_policy=6;HedgingPolicyhedging_policy=7;}}