Skip to content

Commit 9787362

Browse files
authored
server: configurable RPC dial timeout (#27862)
1 parent bea770b commit 9787362

17 files changed

Lines changed: 137 additions & 17 deletions

File tree

.changelog/27862.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:improvement
2+
server: RPC dial timeout is configurable
3+
```

client/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ func NewClient(cfg *config.Config, consulCatalog consul.CatalogAPI, consulProxie
386386
consulProxiesFunc: consulProxiesFunc,
387387
consulServices: consulServices,
388388
start: time.Now(),
389-
connPool: pool.NewPool(logger, clientRPCCache, clientMaxStreams, tlsWrap, cfg.RPCSessionConfig),
389+
connPool: pool.NewPool(logger, clientRPCCache, clientMaxStreams, tlsWrap, cfg.RPCSessionConfig, cfg.RPCDialTimeout),
390390
tlsWrap: tlsWrap,
391391
streamingRpcs: structs.NewStreamingRpcRegistry(),
392392
logger: logger,

client/config/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ type Config struct {
285285
// RPCSessionConfig configures yamux multiplex
286286
RPCSessionConfig *yamux.Config
287287

288+
// RPCDialTimeout is the timeout used when establishing new outbound RPC
289+
// connections to servers. Defaults to 10s.
290+
RPCDialTimeout time.Duration
291+
288292
// PluginLoader is used to load plugins.
289293
PluginLoader loader.PluginCatalog
290294

@@ -925,6 +929,7 @@ func DefaultConfig() *Config {
925929
TemplateConfig: DefaultTemplateConfig(),
926930
RPCHoldTimeout: 5 * time.Second,
927931
RPCSessionConfig: yamux.DefaultConfig(),
932+
RPCDialTimeout: 10 * time.Second,
928933
CNIPath: DefaultCNIPath,
929934
CNIConfigDir: "/opt/cni/config",
930935
CNIInterfacePrefix: "eth",

client/rpc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func bridgedStreamingRpcHandler(sideA io.ReadWriteCloser) structs.StreamingRpcHa
221221
// streaming RPC.
222222
func (c *Client) streamingRpcConn(server *servers.Server, method string) (net.Conn, error) {
223223
// Dial the server
224-
conn, err := net.DialTimeout("tcp", server.Addr.String(), 10*time.Second)
224+
conn, err := net.DialTimeout("tcp", server.Addr.String(), c.config.RPCDialTimeout)
225225
if err != nil {
226226
return nil, err
227227
}

client/testing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func TestRPCOnlyClient(t testing.TB, cb func(c *config.Config), srvAddr net.Addr
120120
}
121121
client.heartbeatStop = newHeartbeatStop(
122122
client.getAllocRunner, time.Second, client.logger, client.shutdownCh)
123-
client.connPool = pool.NewPool(testlog.HCLogger(t), 10*time.Second, 10, nil, yamux.DefaultConfig())
123+
client.connPool = pool.NewPool(testlog.HCLogger(t), 10*time.Second, 10, nil, yamux.DefaultConfig(), 10*time.Second)
124124
client.init()
125125

126126
cancelFunc := func() {

command/agent/agent.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ func convertServerConfig(agentConfig *Config) (*nomad.Config, error) {
573573
if agentConfig.RPC.StreamOpenTimeout > 0 {
574574
conf.RPCSessionConfig.StreamOpenTimeout = agentConfig.RPC.StreamOpenTimeout
575575
}
576+
if agentConfig.RPC.DialTimeout > 0 {
577+
conf.RPCDialTimeout = agentConfig.RPC.DialTimeout
578+
}
576579
}
577580

578581
// Set the TLS config
@@ -946,6 +949,9 @@ func convertClientConfig(agentConfig *Config) (*clientconfig.Config, error) {
946949
if agentConfig.RPC.StreamOpenTimeout > 0 {
947950
conf.RPCSessionConfig.StreamOpenTimeout = agentConfig.RPC.StreamOpenTimeout
948951
}
952+
if agentConfig.RPC.DialTimeout > 0 {
953+
conf.RPCDialTimeout = agentConfig.RPC.DialTimeout
954+
}
949955
}
950956

951957
conf.PreferredAddressFamily = agentConfig.Client.PreferredAddressFamily

command/agent/agent_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,21 @@ func TestConvertClientConfig(t *testing.T) {
817817
must.True(t, cc.DisableAllocationHookMetrics)
818818
},
819819
},
820+
{
821+
name: "rpc dial timeout default",
822+
assert: func(t *testing.T, cc *clientconfig.Config) {
823+
must.Eq(t, 10*time.Second, cc.RPCDialTimeout)
824+
},
825+
},
826+
{
827+
name: "rpc dial timeout override",
828+
modConfig: func(c *Config) {
829+
c.RPC.DialTimeout = 25 * time.Second
830+
},
831+
assert: func(t *testing.T, cc *clientconfig.Config) {
832+
must.Eq(t, 25*time.Second, cc.RPCDialTimeout)
833+
},
834+
},
820835
}
821836
for _, tc := range cases {
822837
t.Run(tc.name, func(t *testing.T) {
@@ -842,6 +857,46 @@ func TestConvertClientConfig(t *testing.T) {
842857
}
843858
}
844859

860+
// TestAgent_ServerConfig_RPCDialTimeout verifies that rpc.dial_timeout is
861+
// plumbed through to the nomad server config, falling back to the default
862+
// when unset.
863+
func TestAgent_ServerConfig_RPCDialTimeout(t *testing.T) {
864+
ci.Parallel(t)
865+
866+
cases := []struct {
867+
name string
868+
modConfig func(*Config)
869+
expectedTO time.Duration
870+
}{
871+
{
872+
name: "default",
873+
expectedTO: 10 * time.Second,
874+
},
875+
{
876+
name: "override",
877+
modConfig: func(c *Config) {
878+
c.RPC.DialTimeout = 25 * time.Second
879+
},
880+
expectedTO: 25 * time.Second,
881+
},
882+
}
883+
884+
for _, tc := range cases {
885+
t.Run(tc.name, func(t *testing.T) {
886+
conf := DevConfig(nil)
887+
require.NoError(t, conf.normalizeAddrs())
888+
if tc.modConfig != nil {
889+
tc.modConfig(conf)
890+
}
891+
892+
nc, err := convertServerConfig(conf)
893+
must.NoError(t, err)
894+
must.NotNil(t, nc)
895+
must.Eq(t, tc.expectedTO, nc.RPCDialTimeout)
896+
})
897+
}
898+
}
899+
845900
func TestAgent_ClientConfig_discovery(t *testing.T) {
846901
ci.Parallel(t)
847902
conf := DefaultConfig()

command/agent/config.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,11 @@ type RPCConfig struct {
872872
// and send a RST to the remote side.
873873
StreamCloseTimeout time.Duration
874874
StreamCloseTimeoutHCL string `hcl:"stream_close_timeout,optional"`
875+
876+
// DialTimeout is the timeout used when establishing new outbound RPC
877+
// connections to peers. A zero value uses the default.
878+
DialTimeout time.Duration
879+
DialTimeoutHCL string `hcl:"dial_timeout,optional"`
875880
}
876881

877882
func (r *RPCConfig) Copy() *RPCConfig {
@@ -921,6 +926,12 @@ func (r *RPCConfig) Merge(rpc *RPCConfig) *RPCConfig {
921926
if rpc.StreamCloseTimeout > 0 {
922927
result.StreamCloseTimeout = rpc.StreamCloseTimeout
923928
}
929+
if rpc.DialTimeoutHCL != "" {
930+
result.DialTimeoutHCL = rpc.DialTimeoutHCL
931+
}
932+
if rpc.DialTimeout > 0 {
933+
result.DialTimeout = rpc.DialTimeout
934+
}
924935
return &result
925936
}
926937

@@ -941,6 +952,9 @@ func (r *RPCConfig) Validate() error {
941952
if r.StreamOpenTimeout < 0 {
942953
return errors.New("rcp.stream_open_timeout must be greater than zero")
943954
}
955+
if r.DialTimeout < 0 {
956+
return errors.New("rpc.dial_timeout must be greater than or equal to zero")
957+
}
944958
}
945959

946960
return nil
@@ -1819,6 +1833,8 @@ func DefaultConfig() *Config {
18191833
StreamOpenTimeoutHCL: "75s",
18201834
StreamCloseTimeout: 5 * time.Minute,
18211835
StreamCloseTimeoutHCL: "5m",
1836+
DialTimeout: 10 * time.Second,
1837+
DialTimeoutHCL: "10s",
18221838
},
18231839
Client: &ClientConfig{
18241840
Enabled: false,

command/agent/config_parse.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ func ParseConfigFile(path string) (*Config, error) {
191191
{"rpc.connection_write_timeout", &c.RPC.ConnectionWriteTimeout, &c.RPC.ConnectionWriteTimeoutHCL, nil},
192192
{"rpc.stream_open_timeout", &c.RPC.StreamOpenTimeout, &c.RPC.StreamOpenTimeoutHCL, nil},
193193
{"rpc.stream_close_timeout", &c.RPC.StreamCloseTimeout, &c.RPC.StreamCloseTimeoutHCL, nil},
194+
{"rpc.dial_timeout", &c.RPC.DialTimeout, &c.RPC.DialTimeoutHCL, nil},
194195
{
195196
"server.client_introduction.default_identity_ttl",
196197
&c.Server.ClientIntroduction.DefaultIdentityTTL,

command/agent/config_parse_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,8 @@ var sample1 = &Config{
868868
StreamOpenTimeoutHCL: "75s",
869869
StreamCloseTimeout: 5 * time.Minute,
870870
StreamCloseTimeoutHCL: "5m",
871+
DialTimeout: 15 * time.Second,
872+
DialTimeoutHCL: "15s",
871873
},
872874
Audit: &config.AuditConfig{
873875
Enabled: pointer.Of(true),

0 commit comments

Comments
 (0)