|
| 1 | +<!-- |
| 2 | + Licensed to the Apache Software Foundation (ASF) under one |
| 3 | + or more contributor license agreements. See the NOTICE file |
| 4 | + distributed with this work for additional information |
| 5 | + regarding copyright ownership. The ASF licenses this file |
| 6 | + to you under the Apache License, Version 2.0 (the |
| 7 | + "License"); you may not use this file except in compliance |
| 8 | + with the License. You may obtain a copy of the License at |
| 9 | + |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + |
| 12 | + Unless required by applicable law or agreed to in writing, |
| 13 | + software distributed under the License is distributed on an |
| 14 | + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | + KIND, either express or implied. See the License for the |
| 16 | + specific language governing permissions and limitations |
| 17 | + under the License. |
| 18 | +--> |
| 19 | + |
| 20 | +Connection pooling |
| 21 | +================== |
| 22 | + |
| 23 | +HttpClient uses connection pools to reuse persistent connections between requests and reduce connection setup overhead. |
| 24 | + |
| 25 | +The main pool implementations are: |
| 26 | + |
| 27 | +* `PoolingHttpClientConnectionManager` for classic (blocking) I/O |
| 28 | +* `PoolingAsyncClientConnectionManager` for async I/O |
| 29 | + |
| 30 | +Both managers: |
| 31 | + |
| 32 | +* Maintain per-route and total connection limits. |
| 33 | +* Reuse idle persistent connections when possible. |
| 34 | +* Enforce time-to-live (TTL) and idle expiry. |
| 35 | + |
| 36 | +Pool concurrency policies |
| 37 | +------------------------- |
| 38 | + |
| 39 | +The concurrency behaviour of the underlying pool is controlled by |
| 40 | +`PoolConcurrencyPolicy`: |
| 41 | + |
| 42 | +* **STRICT** (default) |
| 43 | + Per-route queues and strong fairness. Each route has its own waiter queue; |
| 44 | + connections are handed out in FIFO order per route. This is the safest choice |
| 45 | + for most applications. |
| 46 | + |
| 47 | +* **LAX** |
| 48 | + More relaxed fairness in favour of throughput. Waiters share a global queue |
| 49 | + and busy routes can get more connections under load. This can improve |
| 50 | + utilisation at the cost of strict per-route fairness. |
| 51 | + |
| 52 | +* **OFFLOCK** |
| 53 | + Uses the route-segmented pool implementation (`RouteSegmentedConnPool`) which |
| 54 | + keeps per-route state in independent segments and reduces contention on shared |
| 55 | + structures. The implementation still uses locking where needed; the goal is |
| 56 | + to minimise time spent under hot pool locks. |
| 57 | + |
| 58 | +You can select the policy with the builder: |
| 59 | + |
| 60 | +```java |
| 61 | +final PoolingHttpClientConnectionManager connManager = |
| 62 | + PoolingHttpClientConnectionManagerBuilder.create() |
| 63 | + .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.OFFLOCK) |
| 64 | + .build(); |
| 65 | +``` |
| 66 | + |
| 67 | +Off-lock disposal (blocking pools) |
| 68 | +---------------------------------- |
| 69 | + |
| 70 | +Closing a connection gracefully can be slow (TLS shutdown, FIN/ACK, etc.). If |
| 71 | +this work is done while holding internal pool locks, it can increase latency |
| 72 | +for other threads leasing or releasing connections. |
| 73 | + |
| 74 | +Blocking pools provide an option to move slow graceful closes *off* the hot |
| 75 | +pool locks: |
| 76 | + |
| 77 | +* Immediate closes (`CloseMode.IMMEDIATE`) are always executed on the caller |
| 78 | + thread. |
| 79 | +* Graceful closes can be deferred and performed outside the core pool |
| 80 | + synchronisation. |
| 81 | + |
| 82 | +This behaviour is enabled in the classic manager via: |
| 83 | + |
| 84 | +```java |
| 85 | +final PoolingHttpClientConnectionManager connManager = |
| 86 | + PoolingHttpClientConnectionManagerBuilder.create() |
| 87 | + .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.STRICT) |
| 88 | + .setOffLockDisposalEnabled(true) |
| 89 | + .build(); |
| 90 | +``` |
| 91 | + |
| 92 | +With off-lock disposal enabled: |
| 93 | + |
| 94 | +* The connection is removed from the pool immediately. |
| 95 | +* The actual graceful close is performed later, outside the critical sections |
| 96 | + used by `lease` / `release`. |
| 97 | +* From the caller’s point of view, pool semantics (keep-alive, TTL, idle timeout) |
| 98 | + remain the same. |
| 99 | + |
| 100 | +Configuration hints |
| 101 | +------------------- |
| 102 | + |
| 103 | +* Start with `STRICT` and default disposal behaviour. |
| 104 | +* Consider `LAX` for high-throughput workloads where strict per-route fairness |
| 105 | + is not required. |
| 106 | +* Consider `OFFLOCK` for highly concurrent applications with many routes and |
| 107 | + contention on the pool. |
| 108 | +* Enable off-lock disposal for classic I/O if profiling shows slow graceful |
| 109 | + closes affecting lease/release latency under load. |
0 commit comments