diff --git a/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java b/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java index 8df9363f99f..e0343f83c51 100644 --- a/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java +++ b/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java @@ -54,10 +54,12 @@ // TODO(carl-mastrangelo): rename this AltsProtocolNegotiators. public final class AltsProtocolNegotiator { private static final Logger logger = Logger.getLogger(AltsProtocolNegotiator.class.getName()); - // Avoid performing too many handshakes in parallel, as it may cause queuing in the handshake - // server and cause unbounded blocking on the event loop (b/168808426). This is a workaround until - // there is an async TSI handshaking API to avoid the blocking. - private static final AsyncSemaphore handshakeSemaphore = new AsyncSemaphore(32); + + static final String ALTS_MAX_CONCURRENT_HANDSHAKES_ENV_VARIABLE = + "GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES"; + @VisibleForTesting static final int DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES = 32; + private static final AsyncSemaphore handshakeSemaphore = + new AsyncSemaphore(getAltsMaxConcurrentHandshakes()); @Grpc.TransportAttr public static final Attributes.Key TSI_PEER_KEY = @@ -424,5 +426,30 @@ public SecurityDetails validatePeerObject(Object peerObject) throws GeneralSecur } } + @VisibleForTesting + static int getAltsMaxConcurrentHandshakes(String altsMaxConcurrentHandshakes) { + if (altsMaxConcurrentHandshakes == null) { + return DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES; + } + try { + int effectiveMaxConcurrentHandshakes = Integer.parseInt(altsMaxConcurrentHandshakes); + if (effectiveMaxConcurrentHandshakes < 0) { + logger.warning( + "GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES environment variable set to invalid value."); + return DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES; + } + return effectiveMaxConcurrentHandshakes; + } catch (NumberFormatException e) { + logger.warning( + "GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES environment variable set to invalid value."); + return DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES; + } + } + + private static int getAltsMaxConcurrentHandshakes() { + return getAltsMaxConcurrentHandshakes( + System.getenv(ALTS_MAX_CONCURRENT_HANDSHAKES_ENV_VARIABLE)); + } + private AltsProtocolNegotiator() {} } diff --git a/alts/src/test/java/io/grpc/alts/internal/AltsProtocolNegotiatorTest.java b/alts/src/test/java/io/grpc/alts/internal/AltsProtocolNegotiatorTest.java index b2506288efc..24392af75fd 100644 --- a/alts/src/test/java/io/grpc/alts/internal/AltsProtocolNegotiatorTest.java +++ b/alts/src/test/java/io/grpc/alts/internal/AltsProtocolNegotiatorTest.java @@ -354,6 +354,29 @@ public void peerPropagated() throws Exception { .isEqualTo(SecurityLevel.PRIVACY_AND_INTEGRITY); } + @Test + public void getAltsMaxConcurrentHandshakes_success() throws Exception { + assertThat(AltsProtocolNegotiator.getAltsMaxConcurrentHandshakes("10")).isEqualTo(10); + } + + @Test + public void getAltsMaxConcurrentHandshakes_envVariableNotSet() throws Exception { + assertThat(AltsProtocolNegotiator.getAltsMaxConcurrentHandshakes(null)) + .isEqualTo(AltsProtocolNegotiator.DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES); + } + + @Test + public void getAltsMaxConcurrentHandshakes_envVariableNotANumber() throws Exception { + assertThat(AltsProtocolNegotiator.getAltsMaxConcurrentHandshakes("not-a-number")) + .isEqualTo(AltsProtocolNegotiator.DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES); + } + + @Test + public void getAltsMaxConcurrentHandshakes_envVariableNegative() throws Exception { + assertThat(AltsProtocolNegotiator.getAltsMaxConcurrentHandshakes("-10")) + .isEqualTo(AltsProtocolNegotiator.DEFAULT_ALTS_MAX_CONCURRENT_HANDSHAKES); + } + private void doHandshake() throws Exception { // Capture the client frame and add to the server. assertEquals(1, channel.outboundMessages().size());