Skip to content

Commit e82f055

Browse files
committed
clientv3: configure gRPC message limits in Config
Signed-off-by: Gyuho Lee <[email protected]>
1 parent 4cebdd2 commit e82f055

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

clientv3/client.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ type Client struct {
5656
cfg Config
5757
creds *credentials.TransportCredentials
5858
balancer *healthBalancer
59-
mu sync.Mutex
59+
mu *sync.Mutex
6060

6161
ctx context.Context
6262
cancel context.CancelFunc
@@ -67,6 +67,8 @@ type Client struct {
6767
Password string
6868
// tokenCred is an instance of WithPerRPCCredentials()'s argument
6969
tokenCred *authTokenCredential
70+
71+
callOpts []grpc.CallOption
7072
}
7173

7274
// New creates a new etcdv3 client from a given configuration.
@@ -385,11 +387,30 @@ func newClient(cfg *Config) (*Client, error) {
385387
creds: creds,
386388
ctx: ctx,
387389
cancel: cancel,
390+
mu: new(sync.Mutex),
391+
callOpts: defaultCallOpts,
388392
}
389393
if cfg.Username != "" && cfg.Password != "" {
390394
client.Username = cfg.Username
391395
client.Password = cfg.Password
392396
}
397+
if cfg.MaxCallSendMsgSize > 0 || cfg.MaxCallRecvMsgSize > 0 {
398+
if cfg.MaxCallRecvMsgSize > 0 && cfg.MaxCallSendMsgSize > cfg.MaxCallRecvMsgSize {
399+
return nil, fmt.Errorf("gRPC message recv limit (%d bytes) must be greater than send limit (%d bytes)", cfg.MaxCallRecvMsgSize, cfg.MaxCallSendMsgSize)
400+
}
401+
callOpts := []grpc.CallOption{
402+
defaultFailFast,
403+
defaultMaxCallSendMsgSize,
404+
defaultMaxCallRecvMsgSize,
405+
}
406+
if cfg.MaxCallSendMsgSize > 0 {
407+
callOpts[1] = grpc.MaxCallSendMsgSize(cfg.MaxCallSendMsgSize)
408+
}
409+
if cfg.MaxCallRecvMsgSize > 0 {
410+
callOpts[2] = grpc.MaxCallRecvMsgSize(cfg.MaxCallRecvMsgSize)
411+
}
412+
client.callOpts = callOpts
413+
}
393414

394415
client.balancer = newHealthBalancer(cfg.Endpoints, cfg.DialTimeout, func(ep string) (bool, error) {
395416
return grpcHealthCheck(client, ep)

clientv3/config.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ type Config struct {
4141
// keep-alive probe. If the response is not received in this time, the connection is closed.
4242
DialKeepAliveTimeout time.Duration `json:"dial-keep-alive-timeout"`
4343

44+
// MaxCallSendMsgSize is the client-side request send limit in bytes.
45+
// If 0, it defaults to 2.0 MiB (2 * 1024 * 1024).
46+
// Make sure that "MaxCallSendMsgSize" < server-side default send/recv limit.
47+
// ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
48+
MaxCallSendMsgSize int
49+
50+
// MaxCallRecvMsgSize is the client-side response receive limit.
51+
// If 0, it defaults to "math.MaxInt32", because range response can
52+
// easily exceed request send limits.
53+
// Make sure that "MaxCallRecvMsgSize" >= server-side default send/recv limit.
54+
// ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
55+
MaxCallRecvMsgSize int
56+
4457
// TLS holds the client secure credentials, if any.
4558
TLS *tls.Config
4659

clientv3/grpc_options.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2017 The etcd Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package clientv3
16+
17+
import (
18+
"math"
19+
20+
"google.golang.org/grpc"
21+
)
22+
23+
var (
24+
// Disable gRPC internal retrial logic
25+
// TODO: enable when gRPC retry is stable (FailFast=false)
26+
// Reference:
27+
// - https://github.com/grpc/grpc-go/issues/1532
28+
// - https://github.com/grpc/proposal/blob/master/A6-client-retries.md
29+
defaultFailFast = grpc.FailFast(true)
30+
31+
// client-side request send limit, gRPC default is math.MaxInt32
32+
// Make sure that "client-side send limit < server-side default send/recv limit"
33+
// Same value as "embed.DefaultMaxRequestBytes" plus gRPC overhead bytes
34+
defaultMaxCallSendMsgSize = grpc.MaxCallSendMsgSize(2 * 1024 * 1024)
35+
36+
// client-side response receive limit, gRPC default is 4MB
37+
// Make sure that "client-side receive limit >= server-side default send/recv limit"
38+
// because range response can easily exceed request send limits
39+
// Default to math.MaxInt32; writes exceeding server-side send limit fails anyway
40+
defaultMaxCallRecvMsgSize = grpc.MaxCallRecvMsgSize(math.MaxInt32)
41+
)
42+
43+
// defaultCallOpts defines a list of default "gRPC.CallOption".
44+
// Some options are exposed to "clientv3.Config".
45+
// Defaults will be overridden by the settings in "clientv3.Config".
46+
var defaultCallOpts = []grpc.CallOption{defaultFailFast, defaultMaxCallSendMsgSize, defaultMaxCallRecvMsgSize}

0 commit comments

Comments
 (0)