Skip to content

Commit 8992272

Browse files
committed
docs(gax-grpc): clarify runtime capping of maxResizeDelta and simplify static pool config
1 parent 3a2046f commit 8992272

3 files changed

Lines changed: 53 additions & 7 deletions

File tree

sdk-platform-java/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPool.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,12 +335,22 @@ void resize() {
335335
int delta = tentativeTarget - currentSize;
336336
int dampenedTarget = tentativeTarget;
337337
// Dampen the rate of change if the desired delta exceeds the maximum allowed step size.
338-
if (Math.abs(delta) > settings.getMaxResizeDelta()) {
339-
// Limit the change to maxResizeDelta, maintaining the correct direction (positive or
338+
// Ensure that the step size is capped by the max channel count to handle small pool
339+
// configurations.
340+
int effectiveMaxResizeDelta =
341+
Math.min(settings.getMaxResizeDelta(), settings.getMaxChannelCount());
342+
if (Math.abs(delta) > effectiveMaxResizeDelta) {
343+
// Limit the change to effectiveMaxResizeDelta, maintaining the correct direction (positive or
340344
// negative).
341-
dampenedTarget = currentSize + (int) Math.copySign(settings.getMaxResizeDelta(), delta);
345+
dampenedTarget = currentSize + (int) Math.copySign(effectiveMaxResizeDelta, delta);
342346
}
343347

348+
// Ensure that the calculated dampedTarget value will never exceed the maxChannelCount or fall
349+
// below minChannelCount
350+
dampenedTarget =
351+
Math.max(
352+
settings.getMinChannelCount(), Math.min(settings.getMaxChannelCount(), dampenedTarget));
353+
344354
// Only count as "resized" if the thresholds are crossed and Gax attempts to scale. Checking
345355
// that `dampenedTarget != currentSize` would cause false positives when the pool is within
346356
// bounds but not at the target (target aims for the middle of the bounds)

sdk-platform-java/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/ChannelPoolSettings.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,8 @@ public static ChannelPoolSettings staticallySized(int size) {
139139
.setMaxRpcsPerChannel(Integer.MAX_VALUE)
140140
.setMinChannelCount(size)
141141
.setMaxChannelCount(size)
142-
// Static pools don't resize so this value doesn't affect operation. However,
143-
// validation still checks that resize delta doesn't exceed channel pool size.
144-
.setMaxResizeDelta(Math.min(DEFAULT_MAX_RESIZE_DELTA, size))
142+
// Static pools don't resize so this value doesn't affect operation.
143+
.setMaxResizeDelta(DEFAULT_MAX_RESIZE_DELTA)
145144
.build();
146145
}
147146

@@ -207,7 +206,8 @@ public abstract static class Builder {
207206
/**
208207
* Sets the maximum number of channels that can be added or removed in a single resize cycle.
209208
* This acts as a rate limiter to prevent wild fluctuations. The pool resizes periodically
210-
* according to {@link #RESIZE_INTERVAL} (default 1 minute).
209+
* according to {@link #RESIZE_INTERVAL} (default 1 minute). During resizing, this value is
210+
* effectively capped by the bound configured via {@link #setMaxChannelCount}.
211211
*/
212212
public abstract Builder setMaxResizeDelta(int count);
213213

sdk-platform-java/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/ChannelPoolTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,42 @@ void minChannelsClampedToMaxChannelCountUnderHighLoad() throws Exception {
892892
assertThat(pool.entries.get()).hasSize(5);
893893
}
894894

895+
@Test
896+
void resizeDampenedByMaxResizeDelta() throws Exception {
897+
ScheduledExecutorService executor = Mockito.mock(ScheduledExecutorService.class);
898+
FixedExecutorProvider provider = FixedExecutorProvider.create(executor);
899+
900+
List<ManagedChannel> channels = new ArrayList<>();
901+
ChannelFactory channelFactory = createMockChannelFactory(channels, null);
902+
903+
pool =
904+
new ChannelPool(
905+
ChannelPoolSettings.builder()
906+
.setInitialChannelCount(1)
907+
.setMinRpcsPerChannel(1)
908+
.setMaxRpcsPerChannel(2)
909+
.setMaxResizeDelta(2) // Limit growth to 2 channels per cycle
910+
.setMinChannelCount(1)
911+
.setMaxChannelCount(10)
912+
.build(),
913+
channelFactory,
914+
provider);
915+
assertThat(pool.entries.get()).hasSize(1);
916+
917+
// Add 20 RPCs, which would require 10 channels (20/2)
918+
// Desired delta is +9 (10 - 1)
919+
// maxResizeDelta is 2, so it should be dampened to 2
920+
for (int i = 0; i < 20; i++) {
921+
ClientCalls.futureUnaryCall(
922+
pool.newCall(METHOD_RECOGNIZE, CallOptions.DEFAULT), Color.getDefaultInstance());
923+
}
924+
925+
pool.resize();
926+
927+
// Should be dampened to 1 + 2 = 3 channels
928+
assertThat(pool.entries.get()).hasSize(3);
929+
}
930+
895931
@Test
896932
void maxChannelsClampedToMinChannelCountUnderLowLoad() throws Exception {
897933
ScheduledExecutorService executor = Mockito.mock(ScheduledExecutorService.class);

0 commit comments

Comments
 (0)