Skip to content

Commit

Permalink
Document HTTP client pooling configuration
Browse files Browse the repository at this point in the history
Fixes #11454
  • Loading branch information
yawkat committed Jan 2, 2025
1 parent ecfbe01 commit 6604de1
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ private void doSomeWork() {
// make sure we won't exceed our config setting for pending connections
connectionsToOpen = Math.min(connectionsToOpen, connectionPoolConfiguration.getMaxPendingConnections() - pendingConnectionCount);
// limit the connection count to the protocol-specific settings, but only if that protocol was seen for this pool.
if (http1ConnectionCount > 0) {
// if there's no connections at all, conservatively use the lesser of both limits
if (http1ConnectionCount > 0 || http2ConnectionCount == 0) {
connectionsToOpen = Math.min(connectionsToOpen, connectionPoolConfiguration.getMaxConcurrentHttp1Connections() - http1ConnectionCount);
}
if (http2ConnectionCount > 0) {
if (http2ConnectionCount > 0 || http1ConnectionCount == 0) {
connectionsToOpen = Math.min(connectionsToOpen, connectionPoolConfiguration.getMaxConcurrentHttp2Connections() - http2ConnectionCount);
}

Expand Down
37 changes: 37 additions & 0 deletions src/main/docs/guide/httpClient/nettyPooling.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
The netty client uses a _connection pool_ to share HTTP connections between requests for greater efficiency. The pools
are scoped by service (the service ID you can configure in the `@Client` annotation), and by authority (host and port),
so if you configure e.g. the maximum number of connections, what is meant is the number of connections _per host_.

You can configure the pool through the `micronaut.http.client.pool.\*` properties or, for specific services, via
`micronaut.http.services.*.pool.*`. I'll only mention the simple property name from here on.

HTTP/1.1 and HTTP/2.0 connections are handled and configured separately, because the latter can handle many concurrent
requests on the same connection. For the purposes of pooling, HTTP/3 connections are treated as HTTP/2.0 connections.

When a request is initiated, it is added to a _pending request queue_. The maximum size of this queue is configured
with `max-pending-acquires`, the default is no limit. If the limit is exceeded, the request is rejected. You can also
configure an `acquire-timeout` (no timeout by default).

Once a request is in the pending request queue, it is dispatched to an existing connection. If all connections are
busy but there are still pending requests, a decision is made on whether to create new connections:

* The maximum number of pending connections (i.e. connections that are still being established) may not exceed
`max-pending-connections` (default: 4).
* For HTTP/1.1, the maximum number of connections may not exceed `max-concurrent-http1-connections` (no limit by
default).
* For HTTP/2.0, the maximum number of connections may not exceed `max-concurrent-http2-connections` (default: 1).
* There will be at most as many pending connections as there are pending requests.
The HTTP version is determined by any existing connections in the pool. If the pool is empty, both limits apply, so by
default only one connection is opened at first. For HTTP/2.0, there is also a
`max-concurrent-requests-per-http2-connection` setting that controls how many requests may run on the same HTTP/2.0
connection simultaneously.

Note that a pending connection is not actually associated to a request until it is fully established. A pending request
may time out, but the connection that was created for it will still enter the pool and may be used by another request.

Once a connection is in the pool, there are multiple ways it may terminate and exit the pool. During a request, the
connection may see a read timeout configured by `read-timeout`. When the connection is idle (no request), a similar
read timeout can be configured by `connection-pool-idle-timeout`. A fixed maximum connection lifetime may be configured
using `connect-ttl`, after which the connection will wind down (no new request will be sent and the connection will
terminate after all requests are done). Certain HTTP errors may also lead to a connection shutdown for safety.
1 change: 1 addition & 0 deletions src/main/docs/guide/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ httpClient:
clientHttp2: HTTP/2 Support
clientHttp3: HTTP/3 Support
clientSample: HTTP Client Sample
nettyPooling: Connection pooling in the netty client
contextPropagation:
title: Context propagation
reactorContextPropagation: Reactor context propagation
Expand Down

0 comments on commit 6604de1

Please sign in to comment.