From 6c6315b7ee7b2a885b4d68cd04a055f356b1d1dc Mon Sep 17 00:00:00 2001 From: Javier Aliaga Date: Wed, 21 May 2025 13:10:45 +0200 Subject: [PATCH 1/6] chore: Add grpc keepalives Signed-off-by: Javier Aliaga --- .../main/java/io/dapr/utils/NetworkUtils.java | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java index 522b3e5d7c..de2db3a136 100644 --- a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java +++ b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java @@ -32,6 +32,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import static io.dapr.config.Properties.GRPC_ENDPOINT; @@ -48,7 +49,8 @@ public final class NetworkUtils { private static final long RETRY_WAIT_MILLISECONDS = 1000; - + private static final long KEEP_ALIVE_TIME_SECONDS = 10; + private static final long KEEP_ALIVE_TIMEOUT_SECONDS = 1; // Thanks to https://ihateregex.io/expr/ipv6/ private static final String IPV6_REGEX = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|" + "([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" @@ -68,8 +70,8 @@ public final class NetworkUtils { private static final String GRPC_ENDPOINT_HOSTNAME_REGEX_PART = "(([A-Za-z0-9_\\-\\.]+)|(\\[" + IPV6_REGEX + "\\]))"; - private static final String GRPC_ENDPOINT_DNS_AUTHORITY_REGEX_PART = - "(?dns://)(?" + private static final String GRPC_ENDPOINT_DNS_AUTHORITY_REGEX_PART = "(?dns://)" + + "(?" + GRPC_ENDPOINT_HOSTNAME_REGEX_PART + ":[0-9]+)?/"; private static final String GRPC_ENDPOINT_PARAM_REGEX_PART = "(\\?(?tls\\=((true)|(false))))?"; @@ -144,7 +146,8 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie } catch (Exception e) { throw new DaprException( new DaprError().setErrorCode("TLS_CREDENTIALS_ERROR") - .setMessage("Failed to create insecure TLS credentials"), e); + .setMessage("Failed to create insecure TLS credentials"), + e); } } @@ -155,23 +158,24 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie ManagedChannelBuilder builder = ManagedChannelBuilder.forTarget(settings.endpoint); if (clientCertPath != null && clientKeyPath != null) { - // mTLS case - using client cert and key, with optional CA cert for server authentication + // mTLS case - using client cert and key, with optional CA cert for server + // authentication try ( InputStream clientCertInputStream = new FileInputStream(clientCertPath); InputStream clientKeyInputStream = new FileInputStream(clientKeyPath); - InputStream caCertInputStream = caCertPath != null ? new FileInputStream(caCertPath) : null - ) { + InputStream caCertInputStream = caCertPath != null ? new FileInputStream(caCertPath) : null) { TlsChannelCredentials.Builder builderCreds = TlsChannelCredentials.newBuilder() - .keyManager(clientCertInputStream, clientKeyInputStream); // For client authentication + .keyManager(clientCertInputStream, clientKeyInputStream); // For client authentication if (caCertInputStream != null) { - builderCreds.trustManager(caCertInputStream); // For server authentication + builderCreds.trustManager(caCertInputStream); // For server authentication } ChannelCredentials credentials = builderCreds.build(); builder = Grpc.newChannelBuilder(settings.endpoint, credentials); } catch (IOException e) { throw new DaprException( new DaprError().setErrorCode("TLS_CREDENTIALS_ERROR") - .setMessage("Failed to create mTLS credentials" + (caCertPath != null ? " with CA cert" : "")), e); + .setMessage("Failed to create mTLS credentials" + (caCertPath != null ? " with CA cert" : "")), + e); } } else if (caCertPath != null) { // Simple TLS case - using CA cert only for server authentication @@ -183,7 +187,8 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie } catch (IOException e) { throw new DaprException( new DaprError().setErrorCode("TLS_CREDENTIALS_ERROR") - .setMessage("Failed to create TLS credentials with CA cert"), e); + .setMessage("Failed to create TLS credentials with CA cert"), + e); } } else if (!settings.secure) { builder = builder.usePlaintext(); @@ -194,6 +199,11 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie if (interceptors != null && interceptors.length > 0) { builder = builder.intercept(interceptors); } + + builder.keepAliveTime(KEEP_ALIVE_TIME_SECONDS, TimeUnit.SECONDS) + .keepAliveTimeout(KEEP_ALIVE_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .keepAliveWithoutCalls(true); + return builder.build(); } @@ -206,7 +216,7 @@ static final class GrpcEndpointSettings { final String tlsCaPath; private GrpcEndpointSettings( - String endpoint, boolean secure, String tlsPrivateKeyPath, String tlsCertPath, String tlsCaPath) { + String endpoint, boolean secure, String tlsPrivateKeyPath, String tlsCertPath, String tlsCaPath) { this.endpoint = endpoint; this.secure = secure; this.tlsPrivateKeyPath = tlsPrivateKeyPath; @@ -257,12 +267,12 @@ static GrpcEndpointSettings parse(Properties properties) { var authorityEndpoint = matcher.group("authorityEndpoint"); if (authorityEndpoint != null) { return new GrpcEndpointSettings( - String.format( - "dns://%s/%s:%d", - authorityEndpoint, - address, - port - ), secure, clientKeyPath, clientCertPath, caCertPath); + String.format( + "dns://%s/%s:%d", + authorityEndpoint, + address, + port), + secure, clientKeyPath, clientCertPath, caCertPath); } var socket = matcher.group("socket"); @@ -277,10 +287,9 @@ static GrpcEndpointSettings parse(Properties properties) { } return new GrpcEndpointSettings(String.format( - "dns:///%s:%d", - address, - port - ), secure, clientKeyPath, clientCertPath, caCertPath); + "dns:///%s:%d", + address, + port), secure, clientKeyPath, clientCertPath, caCertPath); } } From 60960ad3788de5ce76e06a14511ab6fd4f56c872 Mon Sep 17 00:00:00 2001 From: Javier Aliaga Date: Wed, 21 May 2025 13:54:15 +0200 Subject: [PATCH 2/6] chore: Make grpc keepalive configurable Signed-off-by: Javier Aliaga --- .../main/java/io/dapr/config/Properties.java | 32 +++++++++++++ .../main/java/io/dapr/utils/NetworkUtils.java | 46 +++++++++++++++---- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/sdk/src/main/java/io/dapr/config/Properties.java b/sdk/src/main/java/io/dapr/config/Properties.java index 98cccf2c48..d0990fade3 100644 --- a/sdk/src/main/java/io/dapr/config/Properties.java +++ b/sdk/src/main/java/io/dapr/config/Properties.java @@ -145,6 +145,38 @@ public class Properties { "DAPR_GRPC_ENDPOINT", null); + /** + * GRPC enable keep alive. + */ + public static final Property GRPC_ENABLE_KEEP_ALIVE = new BooleanProperty( + "dapr.grpc.enableKeepAlive", + "DAPR_GRPC_ENABLE_KEEP_ALIVE", + false); + + /** + * GRPC keep alive time in milliseconds. + */ + public static final Property GRPC_KEEP_ALIVE_TIME_MILLISECONDS = new MillisecondsDurationProperty( + "dapr.grpc.keepAliveTimeSeconds", + "DAPR_GRPC_KEEP_ALIVE_TIME_MILLISECONDS", + Duration.ofMillis(10000)); + + /** + * GRPC keep alive timeout in seconds. + */ + public static final Property GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS = new MillisecondsDurationProperty( + "dapr.grpc.keepAliveTimeoutSeconds", + "DAPR_GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS", + Duration.ofMillis(1000)); + + /** + * GRPC keep alive without calls. + */ + public static final Property GRPC_KEEP_ALIVE_WITHOUT_CALLS = new BooleanProperty( + "dapr.grpc.keepAliveWithoutCalls", + "DAPR_GRPC_KEEP_ALIVE_WITHOUT_CALLS", + false); + /** * GRPC endpoint for remote sidecar connectivity. */ diff --git a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java index de2db3a136..ceaa321b1a 100644 --- a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java +++ b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java @@ -13,6 +13,7 @@ package io.dapr.utils; + import io.dapr.config.Properties; import io.dapr.exceptions.DaprError; import io.dapr.exceptions.DaprException; @@ -32,10 +33,15 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.time.Duration; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; +import static io.dapr.config.Properties.GRPC_ENABLE_KEEP_ALIVE; import static io.dapr.config.Properties.GRPC_ENDPOINT; +import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS; +import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_TIME_MILLISECONDS; +import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_WITHOUT_CALLS; import static io.dapr.config.Properties.GRPC_PORT; import static io.dapr.config.Properties.GRPC_TLS_CA_PATH; import static io.dapr.config.Properties.GRPC_TLS_CERT_PATH; @@ -49,8 +55,7 @@ public final class NetworkUtils { private static final long RETRY_WAIT_MILLISECONDS = 1000; - private static final long KEEP_ALIVE_TIME_SECONDS = 10; - private static final long KEEP_ALIVE_TIMEOUT_SECONDS = 1; + // Thanks to https://ihateregex.io/expr/ipv6/ private static final String IPV6_REGEX = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|" + "([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" @@ -200,9 +205,11 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie builder = builder.intercept(interceptors); } - builder.keepAliveTime(KEEP_ALIVE_TIME_SECONDS, TimeUnit.SECONDS) - .keepAliveTimeout(KEEP_ALIVE_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .keepAliveWithoutCalls(true); + if (settings.enableKeepAlive) { + builder.keepAliveTime(settings.keepAliveTimeSeconds.toMillis(), TimeUnit.MILLISECONDS) + .keepAliveTimeout(settings.keepAliveTimeoutSeconds.toMillis(), TimeUnit.MILLISECONDS) + .keepAliveWithoutCalls(settings.keepAliveWithoutCalls); + } return builder.build(); } @@ -215,13 +222,24 @@ static final class GrpcEndpointSettings { final String tlsCertPath; final String tlsCaPath; + final boolean enableKeepAlive; + final Duration keepAliveTimeSeconds; + final Duration keepAliveTimeoutSeconds; + final boolean keepAliveWithoutCalls; + private GrpcEndpointSettings( - String endpoint, boolean secure, String tlsPrivateKeyPath, String tlsCertPath, String tlsCaPath) { + String endpoint, boolean secure, String tlsPrivateKeyPath, String tlsCertPath, String tlsCaPath, + boolean enableKeepAlive, Duration keepAliveTimeSeconds, Duration keepAliveTimeoutSeconds, + boolean keepAliveWithoutCalls) { this.endpoint = endpoint; this.secure = secure; this.tlsPrivateKeyPath = tlsPrivateKeyPath; this.tlsCertPath = tlsCertPath; this.tlsCaPath = tlsCaPath; + this.enableKeepAlive = enableKeepAlive; + this.keepAliveTimeSeconds = keepAliveTimeSeconds; + this.keepAliveTimeoutSeconds = keepAliveTimeoutSeconds; + this.keepAliveWithoutCalls = keepAliveWithoutCalls; } static GrpcEndpointSettings parse(Properties properties) { @@ -230,6 +248,10 @@ static GrpcEndpointSettings parse(Properties properties) { String clientKeyPath = properties.getValue(GRPC_TLS_KEY_PATH); String clientCertPath = properties.getValue(GRPC_TLS_CERT_PATH); String caCertPath = properties.getValue(GRPC_TLS_CA_PATH); + boolean enablekeepAlive = properties.getValue(GRPC_ENABLE_KEEP_ALIVE); + Duration keepAliveTimeMilliseconds = properties.getValue(GRPC_KEEP_ALIVE_TIME_MILLISECONDS); + Duration keepAliveTimeoutMilliseconds = properties.getValue(GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS); + boolean keepAliveWithoutCalls = properties.getValue(GRPC_KEEP_ALIVE_WITHOUT_CALLS); boolean secure = false; String grpcEndpoint = properties.getValue(GRPC_ENDPOINT); @@ -272,24 +294,28 @@ static GrpcEndpointSettings parse(Properties properties) { authorityEndpoint, address, port), - secure, clientKeyPath, clientCertPath, caCertPath); + secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, keepAliveTimeMilliseconds, + keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); } var socket = matcher.group("socket"); if (socket != null) { - return new GrpcEndpointSettings(socket, secure, clientKeyPath, clientCertPath, caCertPath); + return new GrpcEndpointSettings(socket, secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, + keepAliveTimeMilliseconds, keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); } var vsocket = matcher.group("vsocket"); if (vsocket != null) { - return new GrpcEndpointSettings(vsocket, secure, clientKeyPath, clientCertPath, caCertPath); + return new GrpcEndpointSettings(vsocket, secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, + keepAliveTimeMilliseconds, keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); } } return new GrpcEndpointSettings(String.format( "dns:///%s:%d", address, - port), secure, clientKeyPath, clientCertPath, caCertPath); + port), secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, keepAliveTimeMilliseconds, + keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); } } From faf37b81b2d244655c70a20b767f30ea0d77cdb3 Mon Sep 17 00:00:00 2001 From: Javier Aliaga Date: Wed, 21 May 2025 15:19:01 +0200 Subject: [PATCH 3/6] chore: Fix review comments Signed-off-by: Javier Aliaga --- .../main/java/io/dapr/config/Properties.java | 14 +++---- .../dapr/config/SecondsDurationProperty.java | 39 +++++++++++++++++++ .../main/java/io/dapr/utils/NetworkUtils.java | 24 ++++++------ 3 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 sdk/src/main/java/io/dapr/config/SecondsDurationProperty.java diff --git a/sdk/src/main/java/io/dapr/config/Properties.java b/sdk/src/main/java/io/dapr/config/Properties.java index d0990fade3..af93eb25d0 100644 --- a/sdk/src/main/java/io/dapr/config/Properties.java +++ b/sdk/src/main/java/io/dapr/config/Properties.java @@ -156,18 +156,18 @@ public class Properties { /** * GRPC keep alive time in milliseconds. */ - public static final Property GRPC_KEEP_ALIVE_TIME_MILLISECONDS = new MillisecondsDurationProperty( + public static final Property GRPC_KEEP_ALIVE_TIME_SECONDS = new SecondsDurationProperty( "dapr.grpc.keepAliveTimeSeconds", - "DAPR_GRPC_KEEP_ALIVE_TIME_MILLISECONDS", - Duration.ofMillis(10000)); + "DAPR_GRPC_KEEP_ALIVE_TIME_SECONDS", + Duration.ofSeconds(10)); /** * GRPC keep alive timeout in seconds. */ - public static final Property GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS = new MillisecondsDurationProperty( + public static final Property GRPC_KEEP_ALIVE_TIMEOUT_SECONDS = new SecondsDurationProperty( "dapr.grpc.keepAliveTimeoutSeconds", - "DAPR_GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS", - Duration.ofMillis(1000)); + "DAPR_GRPC_KEEP_ALIVE_TIMEOUT_SECONDS", + Duration.ofSeconds(5)); /** * GRPC keep alive without calls. @@ -175,7 +175,7 @@ public class Properties { public static final Property GRPC_KEEP_ALIVE_WITHOUT_CALLS = new BooleanProperty( "dapr.grpc.keepAliveWithoutCalls", "DAPR_GRPC_KEEP_ALIVE_WITHOUT_CALLS", - false); + true); /** * GRPC endpoint for remote sidecar connectivity. diff --git a/sdk/src/main/java/io/dapr/config/SecondsDurationProperty.java b/sdk/src/main/java/io/dapr/config/SecondsDurationProperty.java new file mode 100644 index 0000000000..02bf1f7ee8 --- /dev/null +++ b/sdk/src/main/java/io/dapr/config/SecondsDurationProperty.java @@ -0,0 +1,39 @@ +/* + * Copyright 2025 The Dapr Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and +limitations under the License. +*/ + +package io.dapr.config; + +import java.time.Duration; + +/** + * Integer configuration property. + */ +public class SecondsDurationProperty extends Property { + + /** + * {@inheritDoc} + */ + SecondsDurationProperty(String name, String envName, Duration defaultValue) { + super(name, envName, defaultValue); + } + + /** + * {@inheritDoc} + */ + @Override + protected Duration parse(String value) { + long longValue = Long.parseLong(value); + return Duration.ofSeconds(longValue); + } + +} diff --git a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java index ceaa321b1a..712ba060a3 100644 --- a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java +++ b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java @@ -39,8 +39,8 @@ import static io.dapr.config.Properties.GRPC_ENABLE_KEEP_ALIVE; import static io.dapr.config.Properties.GRPC_ENDPOINT; -import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS; -import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_TIME_MILLISECONDS; +import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_TIMEOUT_SECONDS; +import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_TIME_SECONDS; import static io.dapr.config.Properties.GRPC_KEEP_ALIVE_WITHOUT_CALLS; import static io.dapr.config.Properties.GRPC_PORT; import static io.dapr.config.Properties.GRPC_TLS_CA_PATH; @@ -206,8 +206,8 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie } if (settings.enableKeepAlive) { - builder.keepAliveTime(settings.keepAliveTimeSeconds.toMillis(), TimeUnit.MILLISECONDS) - .keepAliveTimeout(settings.keepAliveTimeoutSeconds.toMillis(), TimeUnit.MILLISECONDS) + builder.keepAliveTime(settings.keepAliveTimeSeconds.toSeconds(), TimeUnit.SECONDS) + .keepAliveTimeout(settings.keepAliveTimeoutSeconds.toSeconds(), TimeUnit.SECONDS) .keepAliveWithoutCalls(settings.keepAliveWithoutCalls); } @@ -249,8 +249,8 @@ static GrpcEndpointSettings parse(Properties properties) { String clientCertPath = properties.getValue(GRPC_TLS_CERT_PATH); String caCertPath = properties.getValue(GRPC_TLS_CA_PATH); boolean enablekeepAlive = properties.getValue(GRPC_ENABLE_KEEP_ALIVE); - Duration keepAliveTimeMilliseconds = properties.getValue(GRPC_KEEP_ALIVE_TIME_MILLISECONDS); - Duration keepAliveTimeoutMilliseconds = properties.getValue(GRPC_KEEP_ALIVE_TIMEOUT_MILLISECONDS); + Duration keepAliveTimeSeconds = properties.getValue(GRPC_KEEP_ALIVE_TIME_SECONDS); + Duration keepAliveTimeoutSeconds = properties.getValue(GRPC_KEEP_ALIVE_TIMEOUT_SECONDS); boolean keepAliveWithoutCalls = properties.getValue(GRPC_KEEP_ALIVE_WITHOUT_CALLS); boolean secure = false; @@ -294,28 +294,28 @@ static GrpcEndpointSettings parse(Properties properties) { authorityEndpoint, address, port), - secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, keepAliveTimeMilliseconds, - keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); + secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, keepAliveTimeSeconds, + keepAliveTimeoutSeconds, keepAliveWithoutCalls); } var socket = matcher.group("socket"); if (socket != null) { return new GrpcEndpointSettings(socket, secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, - keepAliveTimeMilliseconds, keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); + keepAliveTimeSeconds, keepAliveTimeoutSeconds, keepAliveWithoutCalls); } var vsocket = matcher.group("vsocket"); if (vsocket != null) { return new GrpcEndpointSettings(vsocket, secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, - keepAliveTimeMilliseconds, keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); + keepAliveTimeSeconds, keepAliveTimeoutSeconds, keepAliveWithoutCalls); } } return new GrpcEndpointSettings(String.format( "dns:///%s:%d", address, - port), secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, keepAliveTimeMilliseconds, - keepAliveTimeoutMilliseconds, keepAliveWithoutCalls); + port), secure, clientKeyPath, clientCertPath, caCertPath, enablekeepAlive, keepAliveTimeSeconds, + keepAliveTimeoutSeconds, keepAliveWithoutCalls); } } From 27d7357ee72fb1794c69a4e58b7f4370b3828f39 Mon Sep 17 00:00:00 2001 From: Javier Aliaga Date: Wed, 21 May 2025 15:28:51 +0200 Subject: [PATCH 4/6] chore: Missing keepalive config for GRPC TLS INSECURE Signed-off-by: Javier Aliaga --- sdk/src/main/java/io/dapr/utils/NetworkUtils.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java index 712ba060a3..431bed792e 100644 --- a/sdk/src/main/java/io/dapr/utils/NetworkUtils.java +++ b/sdk/src/main/java/io/dapr/utils/NetworkUtils.java @@ -13,7 +13,6 @@ package io.dapr.utils; - import io.dapr.config.Properties; import io.dapr.exceptions.DaprError; import io.dapr.exceptions.DaprException; @@ -147,6 +146,13 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie if (interceptors != null && interceptors.length > 0) { builder = builder.intercept(interceptors); } + + if (settings.enableKeepAlive) { + builder.keepAliveTime(settings.keepAliveTimeSeconds.toSeconds(), TimeUnit.SECONDS) + .keepAliveTimeout(settings.keepAliveTimeoutSeconds.toSeconds(), TimeUnit.SECONDS) + .keepAliveWithoutCalls(settings.keepAliveWithoutCalls); + } + return builder.build(); } catch (Exception e) { throw new DaprException( From ef0e45f3786db9cff24861c4faea272d715fb338 Mon Sep 17 00:00:00 2001 From: Javier Aliaga Date: Wed, 21 May 2025 16:15:45 +0200 Subject: [PATCH 5/6] chore: Add test Signed-off-by: Javier Aliaga --- .../java/io/dapr/utils/NetworkUtilsTest.java | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java b/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java index 2b4929abd0..a2eee41831 100644 --- a/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java +++ b/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java @@ -15,6 +15,7 @@ import io.dapr.config.Properties; import io.dapr.exceptions.DaprException; +import io.dapr.utils.NetworkUtils.GrpcEndpointSettings; import io.grpc.ManagedChannel; import org.junit.Assert; import org.junit.jupiter.api.AfterAll; @@ -591,4 +592,44 @@ public void testBuildGrpcManagedChannelWithInsecureTlsAndCustomEndpoint() throws // Verify the channel is active and using TLS (not plaintext) Assertions.assertFalse(channel.isTerminated(), "Channel should be active"); } -} + + @Test + public void testBuildGrpcManagedChannelWithKeepAliveDefaults() throws Exception { + var properties = new Properties(Map.of( + Properties.GRPC_ENABLE_KEEP_ALIVE.getName(), "true" + )); + + channel = NetworkUtils.buildGrpcManagedChannel(properties); + channels.add(channel); + + // Verify the channel is active and using TLS (not plaintext) + Assertions.assertFalse(channel.isTerminated(), "Channel should be active"); + } + + @Test + public void testDefaultKeepAliveSettings() throws Exception { + Properties properties = new Properties(); + + GrpcEndpointSettings settings = NetworkUtils.GrpcEndpointSettings.parse(properties); + Assertions.assertEquals(false, settings.enableKeepAlive); + Assertions.assertEquals(10, settings.keepAliveTimeSeconds.getSeconds()); + Assertions.assertEquals(5, settings.keepAliveTimeoutSeconds.getSeconds()); + Assertions.assertEquals(true, settings.keepAliveWithoutCalls); + } + + @Test + public void testDefaultKeepAliveOverride() throws Exception { + Properties properties = new Properties(Map.of( + Properties.GRPC_ENABLE_KEEP_ALIVE.getName(), "true", + Properties.GRPC_KEEP_ALIVE_TIME_SECONDS.getName(), "100", + Properties.GRPC_KEEP_ALIVE_TIMEOUT_SECONDS.getName(), "50", + Properties.GRPC_KEEP_ALIVE_WITHOUT_CALLS.getName(), "false" + )); + + GrpcEndpointSettings settings = NetworkUtils.GrpcEndpointSettings.parse(properties); + Assertions.assertEquals(true, settings.enableKeepAlive); + Assertions.assertEquals(100, settings.keepAliveTimeSeconds.getSeconds()); + Assertions.assertEquals(50, settings.keepAliveTimeoutSeconds.getSeconds()); + Assertions.assertEquals(false, settings.keepAliveWithoutCalls); + } +} \ No newline at end of file From 4761b8559d8663947b8cccd2d5c7fb76d63fbc60 Mon Sep 17 00:00:00 2001 From: Javier Aliaga Date: Wed, 21 May 2025 16:19:34 +0200 Subject: [PATCH 6/6] fix: Comment typo Signed-off-by: Javier Aliaga --- sdk/src/main/java/io/dapr/config/Properties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/main/java/io/dapr/config/Properties.java b/sdk/src/main/java/io/dapr/config/Properties.java index af93eb25d0..51eaf5d25b 100644 --- a/sdk/src/main/java/io/dapr/config/Properties.java +++ b/sdk/src/main/java/io/dapr/config/Properties.java @@ -154,7 +154,7 @@ public class Properties { false); /** - * GRPC keep alive time in milliseconds. + * GRPC keep alive time in seconds. */ public static final Property GRPC_KEEP_ALIVE_TIME_SECONDS = new SecondsDurationProperty( "dapr.grpc.keepAliveTimeSeconds",