32
32
import java .net .InetAddress ;
33
33
import java .net .InetSocketAddress ;
34
34
import java .net .Socket ;
35
+ import java .time .Duration ;
36
+ import java .util .concurrent .TimeUnit ;
35
37
import java .util .regex .Pattern ;
36
38
39
+ import static io .dapr .config .Properties .GRPC_ENABLE_KEEP_ALIVE ;
37
40
import static io .dapr .config .Properties .GRPC_ENDPOINT ;
41
+ import static io .dapr .config .Properties .GRPC_KEEP_ALIVE_TIMEOUT_SECONDS ;
42
+ import static io .dapr .config .Properties .GRPC_KEEP_ALIVE_TIME_SECONDS ;
43
+ import static io .dapr .config .Properties .GRPC_KEEP_ALIVE_WITHOUT_CALLS ;
38
44
import static io .dapr .config .Properties .GRPC_PORT ;
39
45
import static io .dapr .config .Properties .GRPC_TLS_CA_PATH ;
40
46
import static io .dapr .config .Properties .GRPC_TLS_CERT_PATH ;
@@ -68,8 +74,8 @@ public final class NetworkUtils {
68
74
69
75
private static final String GRPC_ENDPOINT_HOSTNAME_REGEX_PART = "(([A-Za-z0-9_\\ -\\ .]+)|(\\ [" + IPV6_REGEX + "\\ ]))" ;
70
76
71
- private static final String GRPC_ENDPOINT_DNS_AUTHORITY_REGEX_PART =
72
- "(?<dnsWithAuthority>dns://) (?<authorityEndpoint>"
77
+ private static final String GRPC_ENDPOINT_DNS_AUTHORITY_REGEX_PART = "(?<dnsWithAuthority>dns://)"
78
+ + " (?<authorityEndpoint>"
73
79
+ GRPC_ENDPOINT_HOSTNAME_REGEX_PART + ":[0-9]+)?/" ;
74
80
75
81
private static final String GRPC_ENDPOINT_PARAM_REGEX_PART = "(\\ ?(?<param>tls\\ =((true)|(false))))?" ;
@@ -140,11 +146,19 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie
140
146
if (interceptors != null && interceptors .length > 0 ) {
141
147
builder = builder .intercept (interceptors );
142
148
}
149
+
150
+ if (settings .enableKeepAlive ) {
151
+ builder .keepAliveTime (settings .keepAliveTimeSeconds .toSeconds (), TimeUnit .SECONDS )
152
+ .keepAliveTimeout (settings .keepAliveTimeoutSeconds .toSeconds (), TimeUnit .SECONDS )
153
+ .keepAliveWithoutCalls (settings .keepAliveWithoutCalls );
154
+ }
155
+
143
156
return builder .build ();
144
157
} catch (Exception e ) {
145
158
throw new DaprException (
146
159
new DaprError ().setErrorCode ("TLS_CREDENTIALS_ERROR" )
147
- .setMessage ("Failed to create insecure TLS credentials" ), e );
160
+ .setMessage ("Failed to create insecure TLS credentials" ),
161
+ e );
148
162
}
149
163
}
150
164
@@ -155,23 +169,24 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie
155
169
ManagedChannelBuilder <?> builder = ManagedChannelBuilder .forTarget (settings .endpoint );
156
170
157
171
if (clientCertPath != null && clientKeyPath != null ) {
158
- // mTLS case - using client cert and key, with optional CA cert for server authentication
172
+ // mTLS case - using client cert and key, with optional CA cert for server
173
+ // authentication
159
174
try (
160
175
InputStream clientCertInputStream = new FileInputStream (clientCertPath );
161
176
InputStream clientKeyInputStream = new FileInputStream (clientKeyPath );
162
- InputStream caCertInputStream = caCertPath != null ? new FileInputStream (caCertPath ) : null
163
- ) {
177
+ InputStream caCertInputStream = caCertPath != null ? new FileInputStream (caCertPath ) : null ) {
164
178
TlsChannelCredentials .Builder builderCreds = TlsChannelCredentials .newBuilder ()
165
- .keyManager (clientCertInputStream , clientKeyInputStream ); // For client authentication
179
+ .keyManager (clientCertInputStream , clientKeyInputStream ); // For client authentication
166
180
if (caCertInputStream != null ) {
167
- builderCreds .trustManager (caCertInputStream ); // For server authentication
181
+ builderCreds .trustManager (caCertInputStream ); // For server authentication
168
182
}
169
183
ChannelCredentials credentials = builderCreds .build ();
170
184
builder = Grpc .newChannelBuilder (settings .endpoint , credentials );
171
185
} catch (IOException e ) {
172
186
throw new DaprException (
173
187
new DaprError ().setErrorCode ("TLS_CREDENTIALS_ERROR" )
174
- .setMessage ("Failed to create mTLS credentials" + (caCertPath != null ? " with CA cert" : "" )), e );
188
+ .setMessage ("Failed to create mTLS credentials" + (caCertPath != null ? " with CA cert" : "" )),
189
+ e );
175
190
}
176
191
} else if (caCertPath != null ) {
177
192
// Simple TLS case - using CA cert only for server authentication
@@ -183,7 +198,8 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie
183
198
} catch (IOException e ) {
184
199
throw new DaprException (
185
200
new DaprError ().setErrorCode ("TLS_CREDENTIALS_ERROR" )
186
- .setMessage ("Failed to create TLS credentials with CA cert" ), e );
201
+ .setMessage ("Failed to create TLS credentials with CA cert" ),
202
+ e );
187
203
}
188
204
} else if (!settings .secure ) {
189
205
builder = builder .usePlaintext ();
@@ -194,6 +210,13 @@ public static ManagedChannel buildGrpcManagedChannel(Properties properties, Clie
194
210
if (interceptors != null && interceptors .length > 0 ) {
195
211
builder = builder .intercept (interceptors );
196
212
}
213
+
214
+ if (settings .enableKeepAlive ) {
215
+ builder .keepAliveTime (settings .keepAliveTimeSeconds .toSeconds (), TimeUnit .SECONDS )
216
+ .keepAliveTimeout (settings .keepAliveTimeoutSeconds .toSeconds (), TimeUnit .SECONDS )
217
+ .keepAliveWithoutCalls (settings .keepAliveWithoutCalls );
218
+ }
219
+
197
220
return builder .build ();
198
221
}
199
222
@@ -205,13 +228,24 @@ static final class GrpcEndpointSettings {
205
228
final String tlsCertPath ;
206
229
final String tlsCaPath ;
207
230
231
+ final boolean enableKeepAlive ;
232
+ final Duration keepAliveTimeSeconds ;
233
+ final Duration keepAliveTimeoutSeconds ;
234
+ final boolean keepAliveWithoutCalls ;
235
+
208
236
private GrpcEndpointSettings (
209
- String endpoint , boolean secure , String tlsPrivateKeyPath , String tlsCertPath , String tlsCaPath ) {
237
+ String endpoint , boolean secure , String tlsPrivateKeyPath , String tlsCertPath , String tlsCaPath ,
238
+ boolean enableKeepAlive , Duration keepAliveTimeSeconds , Duration keepAliveTimeoutSeconds ,
239
+ boolean keepAliveWithoutCalls ) {
210
240
this .endpoint = endpoint ;
211
241
this .secure = secure ;
212
242
this .tlsPrivateKeyPath = tlsPrivateKeyPath ;
213
243
this .tlsCertPath = tlsCertPath ;
214
244
this .tlsCaPath = tlsCaPath ;
245
+ this .enableKeepAlive = enableKeepAlive ;
246
+ this .keepAliveTimeSeconds = keepAliveTimeSeconds ;
247
+ this .keepAliveTimeoutSeconds = keepAliveTimeoutSeconds ;
248
+ this .keepAliveWithoutCalls = keepAliveWithoutCalls ;
215
249
}
216
250
217
251
static GrpcEndpointSettings parse (Properties properties ) {
@@ -220,6 +254,10 @@ static GrpcEndpointSettings parse(Properties properties) {
220
254
String clientKeyPath = properties .getValue (GRPC_TLS_KEY_PATH );
221
255
String clientCertPath = properties .getValue (GRPC_TLS_CERT_PATH );
222
256
String caCertPath = properties .getValue (GRPC_TLS_CA_PATH );
257
+ boolean enablekeepAlive = properties .getValue (GRPC_ENABLE_KEEP_ALIVE );
258
+ Duration keepAliveTimeSeconds = properties .getValue (GRPC_KEEP_ALIVE_TIME_SECONDS );
259
+ Duration keepAliveTimeoutSeconds = properties .getValue (GRPC_KEEP_ALIVE_TIMEOUT_SECONDS );
260
+ boolean keepAliveWithoutCalls = properties .getValue (GRPC_KEEP_ALIVE_WITHOUT_CALLS );
223
261
224
262
boolean secure = false ;
225
263
String grpcEndpoint = properties .getValue (GRPC_ENDPOINT );
@@ -257,30 +295,33 @@ static GrpcEndpointSettings parse(Properties properties) {
257
295
var authorityEndpoint = matcher .group ("authorityEndpoint" );
258
296
if (authorityEndpoint != null ) {
259
297
return new GrpcEndpointSettings (
260
- String .format (
261
- "dns://%s/%s:%d" ,
262
- authorityEndpoint ,
263
- address ,
264
- port
265
- ), secure , clientKeyPath , clientCertPath , caCertPath );
298
+ String .format (
299
+ "dns://%s/%s:%d" ,
300
+ authorityEndpoint ,
301
+ address ,
302
+ port ),
303
+ secure , clientKeyPath , clientCertPath , caCertPath , enablekeepAlive , keepAliveTimeSeconds ,
304
+ keepAliveTimeoutSeconds , keepAliveWithoutCalls );
266
305
}
267
306
268
307
var socket = matcher .group ("socket" );
269
308
if (socket != null ) {
270
- return new GrpcEndpointSettings (socket , secure , clientKeyPath , clientCertPath , caCertPath );
309
+ return new GrpcEndpointSettings (socket , secure , clientKeyPath , clientCertPath , caCertPath , enablekeepAlive ,
310
+ keepAliveTimeSeconds , keepAliveTimeoutSeconds , keepAliveWithoutCalls );
271
311
}
272
312
273
313
var vsocket = matcher .group ("vsocket" );
274
314
if (vsocket != null ) {
275
- return new GrpcEndpointSettings (vsocket , secure , clientKeyPath , clientCertPath , caCertPath );
315
+ return new GrpcEndpointSettings (vsocket , secure , clientKeyPath , clientCertPath , caCertPath , enablekeepAlive ,
316
+ keepAliveTimeSeconds , keepAliveTimeoutSeconds , keepAliveWithoutCalls );
276
317
}
277
318
}
278
319
279
320
return new GrpcEndpointSettings (String .format (
280
- "dns:///%s:%d" ,
281
- address ,
282
- port
283
- ), secure , clientKeyPath , clientCertPath , caCertPath );
321
+ "dns:///%s:%d" ,
322
+ address ,
323
+ port ), secure , clientKeyPath , clientCertPath , caCertPath , enablekeepAlive , keepAliveTimeSeconds ,
324
+ keepAliveTimeoutSeconds , keepAliveWithoutCalls );
284
325
}
285
326
286
327
}
0 commit comments