Skip to content

Commit af74287

Browse files
limdorcoeuvre
andauthored
Remote: Limit max number of gRPC connections by --remote_max_connections. (#14318)
`--remote_max_connections` is only applied to HTTP remote cache. This PR makes it apply to gRPC cache/executor as well. Note that `--remote_max_connections` limits the number of concurrent connections. For HTTP remote cache, one connection could handle one request at one time. For gRPC remote cache/executor, one connection could handle 100+ concurrent requests. So the default value `100` means we could make up to `100` concurrent requests for HTTP remote cache or `10000+` concurrent requests for gRPC remote cache/executor. Fixes: #14178. Closes #14202. PiperOrigin-RevId: 410249542 (cherry picked from commit 8d5973d) Co-authored-by: Chi Wang <[email protected]>
1 parent 039c72e commit af74287

File tree

4 files changed

+52
-21
lines changed

4 files changed

+52
-21
lines changed

src/main/java/com/google/devtools/build/lib/remote/ReferenceCountedChannel.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,13 @@ public ReferenceCounted touch(Object o) {
5656
};
5757

5858
public ReferenceCountedChannel(ChannelConnectionFactory connectionFactory) {
59+
this(connectionFactory, /*maxConnections=*/ 0);
60+
}
61+
62+
public ReferenceCountedChannel(ChannelConnectionFactory connectionFactory, int maxConnections) {
5963
this.dynamicConnectionPool =
60-
new DynamicConnectionPool(connectionFactory, connectionFactory.maxConcurrency());
64+
new DynamicConnectionPool(
65+
connectionFactory, connectionFactory.maxConcurrency(), maxConnections);
6166
}
6267

6368
public boolean isShutdown() {
@@ -81,12 +86,12 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
8186
responseListener) {
8287
@Override
8388
public void onClose(Status status, Metadata trailers) {
84-
super.onClose(status, trailers);
85-
8689
try {
8790
connection.close();
8891
} catch (IOException e) {
8992
throw new AssertionError(e.getMessage(), e);
93+
} finally {
94+
super.onClose(status, trailers);
9095
}
9196
}
9297
},

src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
318318
// based on the resolved IPs of that server. We assume servers normally have 2 IPs. So the
319319
// max concurrency per connection is 100.
320320
int maxConcurrencyPerConnection = 100;
321+
int maxConnections = 0;
322+
if (remoteOptions.remoteMaxConnections > 0) {
323+
maxConnections = remoteOptions.remoteMaxConnections;
324+
}
321325

322326
if (enableRemoteExecution) {
323327
ImmutableList.Builder<ClientInterceptor> interceptors = ImmutableList.builder();
@@ -333,7 +337,8 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
333337
remoteOptions.remoteProxy,
334338
authAndTlsOptions,
335339
interceptors.build(),
336-
maxConcurrencyPerConnection));
340+
maxConcurrencyPerConnection),
341+
maxConnections);
337342

338343
// Create a separate channel if --remote_executor and --remote_cache point to different
339344
// endpoints.
@@ -356,7 +361,8 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
356361
remoteOptions.remoteProxy,
357362
authAndTlsOptions,
358363
interceptors.build(),
359-
maxConcurrencyPerConnection));
364+
maxConcurrencyPerConnection),
365+
maxConnections);
360366
}
361367

362368
if (enableRemoteDownloader) {
@@ -377,7 +383,8 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
377383
remoteOptions.remoteProxy,
378384
authAndTlsOptions,
379385
interceptors.build(),
380-
maxConcurrencyPerConnection));
386+
maxConcurrencyPerConnection),
387+
maxConnections);
381388
}
382389
}
383390

src/main/java/com/google/devtools/build/lib/remote/grpc/DynamicConnectionPool.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
public class DynamicConnectionPool implements ConnectionPool {
3131
private final ConnectionFactory connectionFactory;
3232
private final int maxConcurrencyPerConnection;
33+
private final int maxConnections;
3334
private final AtomicBoolean closed = new AtomicBoolean(false);
3435

3536
@GuardedBy("this")
@@ -40,8 +41,14 @@ public class DynamicConnectionPool implements ConnectionPool {
4041

4142
public DynamicConnectionPool(
4243
ConnectionFactory connectionFactory, int maxConcurrencyPerConnection) {
44+
this(connectionFactory, maxConcurrencyPerConnection, /*maxConnections=*/ 0);
45+
}
46+
47+
public DynamicConnectionPool(
48+
ConnectionFactory connectionFactory, int maxConcurrencyPerConnection, int maxConnections) {
4349
this.connectionFactory = connectionFactory;
4450
this.maxConcurrencyPerConnection = maxConcurrencyPerConnection;
51+
this.maxConnections = maxConnections;
4552
this.factories = new ArrayList<>();
4653
}
4754

@@ -61,12 +68,19 @@ public void close() throws IOException {
6168
}
6269
}
6370

71+
@GuardedBy("this")
72+
private SharedConnectionFactory nextFactory() {
73+
int index = Math.abs(indexTicker % factories.size());
74+
indexTicker += 1;
75+
return factories.get(index);
76+
}
77+
6478
/**
65-
* Performs a simple round robin on the list of {@link SharedConnectionFactory} and return one
66-
* having available connections at this moment.
79+
* Performs a simple round robin on the list of {@link SharedConnectionFactory}.
6780
*
68-
* <p>If no factory has available connections, it will create a new {@link
69-
* SharedConnectionFactory}.
81+
* <p>This will try to find a factory that has available connections at this moment. If no factory
82+
* has available connections, and the number of factories is less than {@link #maxConnections}, it
83+
* will create a new {@link SharedConnectionFactory}.
7084
*/
7185
private SharedConnectionFactory nextAvailableFactory() {
7286
if (closed.get()) {
@@ -75,19 +89,20 @@ private SharedConnectionFactory nextAvailableFactory() {
7589

7690
synchronized (this) {
7791
for (int times = 0; times < factories.size(); ++times) {
78-
int index = Math.abs(indexTicker % factories.size());
79-
indexTicker += 1;
80-
81-
SharedConnectionFactory factory = factories.get(index);
92+
SharedConnectionFactory factory = nextFactory();
8293
if (factory.numAvailableConnections() > 0) {
8394
return factory;
8495
}
8596
}
8697

87-
SharedConnectionFactory factory =
88-
new SharedConnectionFactory(connectionFactory, maxConcurrencyPerConnection);
89-
factories.add(factory);
90-
return factory;
98+
if (maxConnections <= 0 || factories.size() < maxConnections) {
99+
SharedConnectionFactory factory =
100+
new SharedConnectionFactory(connectionFactory, maxConcurrencyPerConnection);
101+
factories.add(factory);
102+
return factory;
103+
} else {
104+
return nextFactory();
105+
}
91106
}
92107
}
93108

src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,13 @@ public final class RemoteOptions extends OptionsBase {
6363
documentationCategory = OptionDocumentationCategory.REMOTE,
6464
effectTags = {OptionEffectTag.HOST_MACHINE_RESOURCE_OPTIMIZATIONS},
6565
help =
66-
"The max. number of concurrent network connections to the remote cache/executor. By "
67-
+ "default Bazel limits the number of TCP connections to 100. Setting this flag to "
68-
+ "0 will make Bazel choose the number of connections automatically.")
66+
"Limit the max number of concurrent connections to remote cache/executor. By default the"
67+
+ " value is 100. Setting this to 0 means no limitation.\n"
68+
+ "For HTTP remote cache, one TCP connection could handle one request at one time, so"
69+
+ " Bazel could make up to --remote_max_connections concurrent requests.\n"
70+
+ "For gRPC remote cache/executor, one gRPC channel could usually handle 100+"
71+
+ " concurrent requests, so Bazel could make around `--remote_max_connections * 100`"
72+
+ " concurrent requests.")
6973
public int remoteMaxConnections;
7074

7175
@Option(

0 commit comments

Comments
 (0)