Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

etcdctl/v3, grpc-proxy: configure --max-send/recv-bytes #9055

Closed
gyuho opened this issue Dec 20, 2017 · 4 comments
Closed

etcdctl/v3, grpc-proxy: configure --max-send/recv-bytes #9055

gyuho opened this issue Dec 20, 2017 · 4 comments

Comments

@gyuho
Copy link
Contributor

gyuho commented Dec 20, 2017

#9047 allows custom gRPC message size limit in clientv3. But neither in v3 etcdctl nor grpc-proxy. If anybody needs this setting in etcdctl or grpc-proxy, here's the git diff.

v3 etcdctl

commit ccb7c9805a5c52312837379e6cc07d31cfdf3163
Author: Gyuho Lee <[email protected]>
Date:   Tue Dec 19 21:49:38 2017 -0800

    Documentation/upgrades: highlight request limit changes in v3.2, v3.3

    Signed-off-by: Gyuho Lee <[email protected]>

diff --git a/Documentation/upgrades/upgrade_3_2.md b/Documentation/upgrades/upgrade_3_2.md
index 441a0c482..8c877fad6 100644
--- a/Documentation/upgrades/upgrade_3_2.md
+++ b/Documentation/upgrades/upgrade_3_2.md
@@ -64,6 +64,101 @@ if err == context.DeadlineExceeded {
 }
 '''

+#### Change in maximum request size limits (>=3.2.10)
+
+3.2.10 and 3.2.11 allow custom request size limits in server side. >=3.2.12 allows custom request size limits for both server and **client side**.
+
+Server-side request limits can be configured with `--max-request-bytes` flag:
+
+'''bash
+# limits request size to 1.5 KiB
+etcd --max-request-bytes 1536
+
+# client writes exceeding 1.5 KiB will be rejected
+etcdctl put foo [LARGE VALUE...]
+# etcdserver: request is too large
+'''
+
+Or configure `embed.Config.MaxRequestBytes` field:
+
+'''go
+import "github.com/coreos/etcd/embed"
+import "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+
+// limit requests to 5 MiB
+cfg := embed.NewConfig()
+cfg.MaxRequestBytes = 5 * 1024 * 1024
+
+// client writes exceeding 5 MiB will be rejected
+_, err := cli.Put(ctx, "foo", [LARGE VALUE...])
+err == rpctypes.ErrRequestTooLarge
+'''
+
+**If not specified, server-side limit defaults to 1.5 MiB**.
+
+Client-side request limits must be configured based on server-side limits.
+
+'''bash
+# limits request size to 1.5 KiB
+etcd --max-request-bytes 1536
+
+etcdctl put foo bar
+# OK
+
+# request exceeding server send limit
+etcdctl put foo [2 KiB value...]
+# etcdserver: request is too large
+
+# request exceeding client send limit
+etcdctl put foo bar --max-send-bytes 1
+# Error: rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (10 vs. 1)
+
+# request exceeding client receive limit
+etcdctl get foo bar --max-send-bytes 5 --max-recv-bytes 5
+# Error: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (48 vs. 5)
+'''
+
+With clientv3:
+
+'''bash
+# limits request size to 1 MiB
+etcd --max-request-bytes 1048576
+'''
+
+'''go
+import "github.com/coreos/etcd/clientv3"
+
+cli, _ := clientv3.New(clientv3.Config{
+    Endpoints: []string{"127.0.0.1:2379"},
+    MaxCallSendMsgSize: 2 * 1024 * 1024,
+    MaxCallRecvMsgSize: 3 * 1024 * 1024,
+})
+
+
+// client writes exceeding "--max-request-bytes" will be rejected from etcd server
+_, err := cli.Put(ctx, "foo", strings.Repeat("a", 1*1024*1024+5))
+err == rpctypes.ErrRequestTooLarge
+
+
+// client writes exceeding "MaxCallSendMsgSize" will be rejected from client-side
+_, err = cli.Put(ctx, "foo", strings.Repeat("a", 5*1024*1024))
+err.Error() == "rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (5242890 vs. 2097152)"
+
+
+// some writes under limits
+for i := range []int{0,1,2,3,4} {
+    _, err = cli.Put(ctx, fmt.Sprintf("foo%d", i), strings.Repeat("a", 1*1024*1024-500))
+    if err != nil {
+        panic(err)
+    }
+}
+// client reads exceeding "MaxCallRecvMsgSize" will be rejected from client-side
+_, err = cli.Get(ctx, "foo", clientv3.WithPrefix())
+err.Error() == "rpc error: code = ResourceExhausted desc = grpc: received message larger than max (5240509 vs. 3145728)"
+'''
+
+**If not specified, client-side send limit defaults to 1.5 MiB and receive limit to `math.MaxInt32`**. Please see [clientv3 godoc](https://godoc.org/github.com/coreos/etcd/clientv3#Config) for more detail.
+
 #### Change in `--listen-peer-urls` and `--listen-client-urls`

 3.2 now rejects domains names for `--listen-peer-urls` and `--listen-client-urls` (3.1 only prints out warnings), since domain name is invalid for network interface binding. Make sure that those URLs are properly formated as `scheme://IP:port`.
diff --git a/Documentation/upgrades/upgrade_3_3.md b/Documentation/upgrades/upgrade_3_3.md
index 2e724a464..ad92bed02 100644
--- a/Documentation/upgrades/upgrade_3_3.md
+++ b/Documentation/upgrades/upgrade_3_3.md
@@ -111,6 +111,99 @@ curl -L http://localhost:2379/v3beta/kv/put \

 Requests to `/v3alpha` endpoints will redirect to `/v3beta`, and `/v3alpha` will be removed in 3.4 release.

+#### Change in maximum request size limits
+
+3.3 now allows custom request size limits for both server and **client side**.
+
+Server-side request limits can be configured with `--max-request-bytes` flag:
+
+'''bash
+# limits request size to 1.5 KiB
+etcd --max-request-bytes 1536
+
+# client writes exceeding 1.5 KiB will be rejected
+etcdctl put foo [LARGE VALUE...]
+# etcdserver: request is too large
+'''
+
+Or configure `embed.Config.MaxRequestBytes` field:
+
+'''go
+import "github.com/coreos/etcd/embed"
+import "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+
+// limit requests to 5 MiB
+cfg := embed.NewConfig()
+cfg.MaxRequestBytes = 5 * 1024 * 1024
+
+// client writes exceeding 5 MiB will be rejected
+_, err := cli.Put(ctx, "foo", [LARGE VALUE...])
+err == rpctypes.ErrRequestTooLarge
+'''
+
+**If not specified, server-side limit defaults to 1.5 MiB**.
+
+Client-side request limits must be configured based on server-side limits.
+
+'''bash
+# limits request size to 1.5 KiB
+etcd --max-request-bytes 1536
+
+etcdctl put foo bar
+# OK
+
+# request exceeding server send limit
+etcdctl put foo [2 KiB value...]
+# etcdserver: request is too large
+
+# request exceeding client send limit
+etcdctl put foo bar --max-send-bytes 1
+# Error: rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (10 vs. 1)
+
+# request exceeding client receive limit
+etcdctl get foo bar --max-send-bytes 5 --max-recv-bytes 5
+# Error: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (48 vs. 5)
+'''
+
+With clientv3:
+
+'''bash
+# limits request size to 1 MiB
+etcd --max-request-bytes 1048576
+'''
+
+'''go
+import "github.com/coreos/etcd/clientv3"
+
+cli, _ := clientv3.New(clientv3.Config{
+    Endpoints: []string{"127.0.0.1:2379"},
+    MaxCallSendMsgSize: 2 * 1024 * 1024,
+    MaxCallRecvMsgSize: 3 * 1024 * 1024,
+})
+
+
+// client writes exceeding "--max-request-bytes" will be rejected from etcd server
+_, err := cli.Put(ctx, "foo", strings.Repeat("a", 1*1024*1024+5))
+err == rpctypes.ErrRequestTooLarge
+
+
+// client writes exceeding "MaxCallSendMsgSize" will be rejected from client-side
+_, err = cli.Put(ctx, "foo", strings.Repeat("a", 5*1024*1024))
+err.Error() == "rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (5242890 vs. 2097152)"
+
+
+// some writes under limits
+for i := range []int{0,1,2,3,4} {
+    _, err = cli.Put(ctx, fmt.Sprintf("foo%d", i), strings.Repeat("a", 1*1024*1024-500))
+    if err != nil {
+        panic(err)
+    }
+}
+// client reads exceeding "MaxCallRecvMsgSize" will be rejected from client-side
+_, err = cli.Get(ctx, "foo", clientv3.WithPrefix())
+err.Error() == "rpc error: code = ResourceExhausted desc = grpc: received message larger than max (5240509 vs. 3145728)"
+'''
+
 #### Change in clientv3 `Snapshot` API error type

 Previously, clientv3 `Snapshot` API returned raw [`grpc/*status.statusError`] type error. v3.3 now translates those errors to corresponding public error types, to be consistent with other APIs.
commit 7525c173a447000aa88586aee3c059ac19c1848b
Author: Gyuho Lee <[email protected]>
Date:   Tue Dec 19 22:54:22 2017 -0800

    etcdctl/ctlv3: add "--max-send-bytes","--max-recv-bytes" flags
    
    Signed-off-by: Gyuho Lee <[email protected]>

diff --git a/etcdctl/ctlv3/command/ep_command.go b/etcdctl/ctlv3/command/ep_command.go
index a1534b4df..0b2067c3e 100644
--- a/etcdctl/ctlv3/command/ep_command.go
+++ b/etcdctl/ctlv3/command/ep_command.go
@@ -85,9 +85,11 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) {
 	ka := keepAliveTimeFromCmd(cmd)
 	kat := keepAliveTimeoutFromCmd(cmd)
 	auth := authCfgFromCmd(cmd)
+	maxCallSendMsgSize := maxSendBytesFromCmd(cmd)
+	maxCallRecvMsgSize := maxRecvBytesFromCmd(cmd)
 	cfgs := []*v3.Config{}
 	for _, ep := range endpointsFromCluster(cmd) {
-		cfg, err := newClientCfg([]string{ep}, dt, ka, kat, sec, auth)
+		cfg, err := newClientCfg([]string{ep}, dt, ka, kat, sec, auth, maxCallSendMsgSize, maxCallRecvMsgSize)
 		if err != nil {
 			ExitWithError(ExitBadArgs, err)
 		}
diff --git a/etcdctl/ctlv3/command/global.go b/etcdctl/ctlv3/command/global.go
index ce607e82a..5f182e7ef 100644
--- a/etcdctl/ctlv3/command/global.go
+++ b/etcdctl/ctlv3/command/global.go
@@ -46,6 +46,9 @@ type GlobalFlags struct {
 	KeepAliveTime      time.Duration
 	KeepAliveTimeout   time.Duration
 
+	MaxCallSendMsgSize int
+	MaxCallRecvMsgSize int
+
 	TLS transport.TLSInfo
 
 	OutputFormat string
@@ -93,12 +96,14 @@ func initDisplayFromCmd(cmd *cobra.Command) {
 }
 
 type clientConfig struct {
-	endpoints        []string
-	dialTimeout      time.Duration
-	keepAliveTime    time.Duration
-	keepAliveTimeout time.Duration
-	scfg             *secureCfg
-	acfg             *authCfg
+	endpoints          []string
+	dialTimeout        time.Duration
+	keepAliveTime      time.Duration
+	keepAliveTimeout   time.Duration
+	maxCallSendMsgSize int
+	maxCallRecvMsgSize int
+	scfg               *secureCfg
+	acfg               *authCfg
 }
 
 func clientConfigFromCmd(cmd *cobra.Command) *clientConfig {
@@ -127,6 +132,8 @@ func clientConfigFromCmd(cmd *cobra.Command) *clientConfig {
 	cfg.dialTimeout = dialTimeoutFromCmd(cmd)
 	cfg.keepAliveTime = keepAliveTimeFromCmd(cmd)
 	cfg.keepAliveTimeout = keepAliveTimeoutFromCmd(cmd)
+	cfg.maxCallSendMsgSize = maxSendBytesFromCmd(cmd)
+	cfg.maxCallRecvMsgSize = maxRecvBytesFromCmd(cmd)
 
 	cfg.scfg = secureCfgFromCmd(cmd)
 	cfg.acfg = authCfgFromCmd(cmd)
@@ -141,7 +148,7 @@ func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client {
 }
 
 func (cc *clientConfig) mustClient() *clientv3.Client {
-	cfg, err := newClientCfg(cc.endpoints, cc.dialTimeout, cc.keepAliveTime, cc.keepAliveTimeout, cc.scfg, cc.acfg)
+	cfg, err := newClientCfg(cc.endpoints, cc.dialTimeout, cc.keepAliveTime, cc.keepAliveTimeout, cc.scfg, cc.acfg, cc.maxCallSendMsgSize, cc.maxCallRecvMsgSize)
 	if err != nil {
 		ExitWithError(ExitBadArgs, err)
 	}
@@ -154,7 +161,7 @@ func (cc *clientConfig) mustClient() *clientv3.Client {
 	return client
 }
 
-func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeout time.Duration, scfg *secureCfg, acfg *authCfg) (*clientv3.Config, error) {
+func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeout time.Duration, scfg *secureCfg, acfg *authCfg, maxCallSendMsgSize int, maxCallRecvMsgSize int) (*clientv3.Config, error) {
 	// set tls if any one tls option set
 	var cfgtls *transport.TLSInfo
 	tlsinfo := transport.TLSInfo{}
@@ -183,6 +190,8 @@ func newClientCfg(endpoints []string, dialTimeout, keepAliveTime, keepAliveTimeo
 		DialTimeout:          dialTimeout,
 		DialKeepAliveTime:    keepAliveTime,
 		DialKeepAliveTimeout: keepAliveTimeout,
+		MaxCallSendMsgSize:   maxCallSendMsgSize,
+		MaxCallRecvMsgSize:   maxCallRecvMsgSize,
 	}
 
 	if cfgtls != nil {
@@ -249,6 +258,22 @@ func keepAliveTimeoutFromCmd(cmd *cobra.Command) time.Duration {
 	return keepAliveTimeout
 }
 
+func maxSendBytesFromCmd(cmd *cobra.Command) int {
+	maxSendBytes, err := cmd.Flags().GetInt("max-send-bytes")
+	if err != nil {
+		ExitWithError(ExitError, err)
+	}
+	return maxSendBytes
+}
+
+func maxRecvBytesFromCmd(cmd *cobra.Command) int {
+	maxRecvBytes, err := cmd.Flags().GetInt("max-recv-bytes")
+	if err != nil {
+		ExitWithError(ExitError, err)
+	}
+	return maxRecvBytes
+}
+
 func secureCfgFromCmd(cmd *cobra.Command) *secureCfg {
 	cert, key, cacert := keyAndCertFromCmd(cmd)
 	insecureTr := insecureTransportFromCmd(cmd)
diff --git a/etcdctl/ctlv3/ctl.go b/etcdctl/ctlv3/ctl.go
index 8692084cf..4e12c9750 100644
--- a/etcdctl/ctlv3/ctl.go
+++ b/etcdctl/ctlv3/ctl.go
@@ -16,6 +16,7 @@
 package ctlv3
 
 import (
+	"math"
 	"time"
 
 	"github.com/coreos/etcd/etcdctl/ctlv3/command"
@@ -55,6 +56,8 @@ func init() {
 	rootCmd.PersistentFlags().DurationVar(&globalFlags.CommandTimeOut, "command-timeout", defaultCommandTimeOut, "timeout for short running command (excluding dial timeout)")
 	rootCmd.PersistentFlags().DurationVar(&globalFlags.KeepAliveTime, "keepalive-time", defaultKeepAliveTime, "keepalive time for client connections")
 	rootCmd.PersistentFlags().DurationVar(&globalFlags.KeepAliveTimeout, "keepalive-timeout", defaultKeepAliveTimeOut, "keepalive timeout for client connections")
+	rootCmd.PersistentFlags().IntVar(&globalFlags.MaxCallSendMsgSize, "max-send-bytes", 1.5*1024*1024, "client-side message send limits in bytes (default value is 1.5 MiB)")
+	rootCmd.PersistentFlags().IntVar(&globalFlags.MaxCallRecvMsgSize, "max-recv-bytes", math.MaxInt32, "client-side message receive limits in bytes (default value is math.MaxInt32)")
 
 	// TODO: secure by default when etcd enables secure gRPC by default.
 	rootCmd.PersistentFlags().BoolVar(&globalFlags.Insecure, "insecure-transport", true, "disable transport security for client connections")
commit 935793a2bce3d94682a72a37101b47e914389b1c
Author: Gyuho Lee <[email protected]>
Date:   Wed Dec 20 00:07:44 2017 -0800

    e2e: test request bytes both for server and client sides
    
    Signed-off-by: Gyuho Lee <[email protected]>

diff --git a/e2e/cluster_test.go b/e2e/cluster_test.go
index 69896dd48..9e2fce4eb 100644
--- a/e2e/cluster_test.go
+++ b/e2e/cluster_test.go
@@ -19,6 +19,7 @@ import (
 	"io/ioutil"
 	"net/url"
 	"os"
+	"strconv"
 	"strings"
 
 	"github.com/coreos/etcd/etcdserver"
@@ -117,6 +118,8 @@ type etcdProcessClusterConfig struct {
 	quotaBackendBytes   int64
 	noStrictReconfig    bool
 	initialCorruptCheck bool
+
+	maxRequestBytes int
 }
 
 // newEtcdProcessCluster launches a new cluster from etcd processes, returning
@@ -222,6 +225,10 @@ func (cfg *etcdProcessClusterConfig) etcdServerProcessConfigs() []*etcdServerPro
 				"--quota-backend-bytes", fmt.Sprintf("%d", cfg.quotaBackendBytes),
 			)
 		}
+		if cfg.maxRequestBytes > 0 {
+			args = append(args,
+				"--max-request-bytes", strconv.Itoa(cfg.maxRequestBytes))
+		}
 		if cfg.noStrictReconfig {
 			args = append(args, "--strict-reconfig-check=false")
 		}
diff --git a/e2e/ctl_v3_kv_test.go b/e2e/ctl_v3_kv_test.go
index 2e14bea64..3ef4cc70a 100644
--- a/e2e/ctl_v3_kv_test.go
+++ b/e2e/ctl_v3_kv_test.go
@@ -88,6 +88,44 @@ func putTest(cx ctlCtx) {
 	}
 }
 
+func TestCtlV3PutRequestTooLarge(t *testing.T) {
+	cfg := configNoTLS
+	cfg.maxRequestBytes = 15
+	testCtl(t, func(cx ctlCtx) {
+		exp := "Error: etcdserver: request is too large"
+		cmdArgs := append(cx.PrefixArgs(), "put", "foo", strings.Repeat("a", 30))
+		if err := spawnWithExpect(cmdArgs, exp); err != nil {
+			cx.t.Fatalf("expected %q, got %q", exp, err.Error())
+		}
+	}, withCfg(cfg))
+}
+
+func TestCtlV3PutSendLimit(t *testing.T) {
+	testCtl(t, func(cx ctlCtx) {
+		exp := "Error: rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (37 vs. 10)"
+		cmdArgs := append(cx.PrefixArgs(), "get", "foo", strings.Repeat("a", 30))
+		if err := spawnWithExpect(cmdArgs, exp); err != nil {
+			cx.t.Fatalf("expected %q, got %q", exp, err.Error())
+		}
+	}, withCfg(configNoTLS), withMaxSendBytes(10))
+}
+
+func TestCtlV3GetRecvLimit(t *testing.T) {
+	testCtl(t, func(cx ctlCtx) {
+		for i := range []int{0, 1, 2} {
+			if err := ctlV3Put(cx, fmt.Sprintf("foo%d", i), "bar", ""); err != nil {
+				fmt.Println(i, err)
+				cx.t.Fatal(err)
+			}
+		}
+		exp := "Error: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (86 vs. 30)"
+		cmdArgs := append(cx.PrefixArgs(), "get", "foo", "--prefix")
+		if err := spawnWithExpect(cmdArgs, exp); err != nil {
+			cx.t.Fatalf("expected %q, got %q", exp, err.Error())
+		}
+	}, withCfg(configNoTLS), withMaxSendBytes(20), withMaxRecvBytes(30))
+}
+
 func putTestIgnoreValue(cx ctlCtx) {
 	if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
 		cx.t.Fatal(err)
diff --git a/e2e/ctl_v3_test.go b/e2e/ctl_v3_test.go
index 396e6c184..d76e1d8d9 100644
--- a/e2e/ctl_v3_test.go
+++ b/e2e/ctl_v3_test.go
@@ -17,6 +17,7 @@ package e2e
 import (
 	"fmt"
 	"os"
+	"strconv"
 	"strings"
 	"testing"
 	"time"
@@ -64,6 +65,9 @@ type ctlCtx struct {
 
 	dialTimeout time.Duration
 
+	maxSendBytes int
+	maxRecvBytes int
+
 	quorum      bool // if true, set up 3-node cluster and linearizable read
 	interactive bool
 
@@ -93,6 +97,14 @@ func withDialTimeout(timeout time.Duration) ctlOption {
 	return func(cx *ctlCtx) { cx.dialTimeout = timeout }
 }
 
+func withMaxSendBytes(n int) ctlOption {
+	return func(cx *ctlCtx) { cx.maxSendBytes = n }
+}
+
+func withMaxRecvBytes(n int) ctlOption {
+	return func(cx *ctlCtx) { cx.maxRecvBytes = n }
+}
+
 func withQuorum() ctlOption {
 	return func(cx *ctlCtx) { cx.quorum = true }
 }
@@ -185,6 +197,12 @@ func (cx *ctlCtx) prefixArgs(eps []string) []string {
 	fmap := make(map[string]string)
 	fmap["endpoints"] = strings.Join(eps, ",")
 	fmap["dial-timeout"] = cx.dialTimeout.String()
+	if cx.maxSendBytes > 0 {
+		fmap["max-send-bytes"] = strconv.Itoa(cx.maxSendBytes)
+	}
+	if cx.maxRecvBytes > 0 {
+		fmap["max-recv-bytes"] = strconv.Itoa(cx.maxRecvBytes)
+	}
 	if cx.epc.cfg.clientTLS == clientTLS {
 		if cx.epc.cfg.isClientAutoTLS {
 			fmap["insecure-transport"] = "false"

grpc-proxy

commit 595f61fe891a3daa86696230e4c411af8bcd7f7c
Author: Gyuho Lee <[email protected]>
Date:   Tue Dec 19 22:53:58 2017 -0800

    etcdmain/grpc-proxy: add "--max-send-bytes","--max-recv-bytes" flags
    
    Signed-off-by: Gyuho Lee <[email protected]>

diff --git a/etcdmain/grpc_proxy.go b/etcdmain/grpc_proxy.go
index 41f71c70e..7c52fbe72 100644
--- a/etcdmain/grpc_proxy.go
+++ b/etcdmain/grpc_proxy.go
@@ -75,6 +75,9 @@ var (
 
 	grpcProxyEnablePprof    bool
 	grpcProxyEnableOrdering bool
+
+	grpcMaxCallSendMsgSize int
+	grpcMaxCallRecvMsgSize int
 )
 
 func init() {
@@ -110,6 +113,8 @@ func newGRPCProxyStartCommand() *cobra.Command {
 	cmd.Flags().StringVar(&grpcProxyNamespace, "namespace", "", "string to prefix to all keys for namespacing requests")
 	cmd.Flags().BoolVar(&grpcProxyEnablePprof, "enable-pprof", false, `Enable runtime profiling data via HTTP server. Address is at client URL + "/debug/pprof/"`)
 	cmd.Flags().StringVar(&grpcProxyDataDir, "data-dir", "default.proxy", "Data directory for persistent data")
+	cmd.Flags().IntVar(&grpcMaxCallSendMsgSize, "max-send-bytes", 1.5*1024*1024, "message send limits in bytes (default value is 1.5 MiB)")
+	cmd.Flags().IntVar(&grpcMaxCallRecvMsgSize, "max-recv-bytes", math.MaxInt32, "message receive limits in bytes (default value is math.MaxInt32)")
 
 	// client TLS for connecting to server
 	cmd.Flags().StringVar(&grpcProxyCert, "cert", "", "identify secure connections with etcd servers using this TLS certificate file")
@@ -222,6 +227,12 @@ func newClientCfg(eps []string) (*clientv3.Config, error) {
 		Endpoints:   eps,
 		DialTimeout: 5 * time.Second,
 	}
+	if grpcMaxCallSendMsgSize > 0 {
+		cfg.MaxCallSendMsgSize = grpcMaxCallSendMsgSize
+	}
+	if grpcMaxCallRecvMsgSize > 0 {
+		cfg.MaxCallRecvMsgSize = grpcMaxCallRecvMsgSize
+	}
 	tls := newTLS(grpcProxyCA, grpcProxyCert, grpcProxyKey)
 	if tls == nil && grpcProxyInsecureSkipTLSVerify {
 		tls = &transport.TLSInfo{}
@zbindenren
Copy link
Contributor

+1

Without this option we cannot use the proxy.

@xiang90
Copy link
Contributor

xiang90 commented Jan 29, 2018

@zbindenren would you like to help on this?

@gyuho
Copy link
Contributor Author

gyuho commented Jan 29, 2018

@zbindenren We have official 3.3 planned for February 1, 2018. If we can do it before then, we will include that in the release. Thanks!

@zbindenren
Copy link
Contributor

zbindenren commented Jan 30, 2018

@xiang90 created a pull request #9250 for grpc-proxy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants