@@ -111,9 +111,27 @@ public class Constants {
111111 */
112112 public static final String DEFAULT_CONNECT_TIMEOUT = "1000" ;
113113 /**
114- * Default maximum number of connections 20480
115- */
116- public static final String DEFAULT_MAX_CONNECTIONS = "20480" ;
114+ * Default maximum number of connections.
115+ *
116+ * <p>200 covers the great majority of internal RPC workloads while keeping the worst-case
117+ * resource footprint bounded:</p>
118+ * <ul>
119+ * <li>By Little's Law (concurrent in-flight = QPS × RT) 200 connections sustain
120+ * e.g. {@code QPS=20000 × RT=10ms} or {@code QPS=2000 × RT=100ms} on the HTTP/1.1
121+ * path where each connection serves one request at a time;</li>
122+ * <li>Far below the Linux default ephemeral-port range (~28k usable) so a connection
123+ * storm against an unreachable backend cannot exhaust the port pool;</li>
124+ * <li>Friendly to backend LBs whose per-source keep-alive limits are typically in the
125+ * low thousands.</li>
126+ * </ul>
127+ *
128+ * <p>Workloads that genuinely need more (high-fanout aggregation services, very high QPS
129+ * with long RT) should override per-{@code BackendConfig} via {@code maxConns}.</p>
130+ *
131+ * <p>Note: the trpc protocol path does not read this field — it sizes the connection pool
132+ * via {@code connsPerAddr} (default 4). Only the HTTP / HTTP/2 paths consume it.</p>
133+ */
134+ public static final String DEFAULT_MAX_CONNECTIONS = "200" ;
117135 /**
118136 * Default maximum payload limit 10M
119137 */
@@ -156,9 +174,36 @@ public class Constants {
156174 */
157175 public static final String DEFAULT_SERVER_IDLE_TIMEOUT = "240000" ;
158176 /**
159- * Default number of connections per address 2
160- */
161- public static final String DEFAULT_CONNECTIONS_PERADDR = "2" ;
177+ * Default number of long-lived TCP connections to a single peer address.
178+ *
179+ * <p>Each business request is dispatched round-robin across these N channels
180+ * ({@code channelIdx.getAndIncrement() % N}); on a single channel Netty multiplexes many
181+ * in-flight RPCs via the protocol-level sequence id, so {@code N=1} would already saturate
182+ * a 1Gbps link in pure throughput. The default of <b>4</b> is chosen so that:</p>
183+ * <ul>
184+ * <li>Multiple Netty {@code EventLoop} threads run in parallel for a single peer —
185+ * no single EventLoop becomes a CPU bottleneck under high QPS;</li>
186+ * <li>Failure-domain isolation: when a channel is invalidated by READ_IDLE / RST /
187+ * half-close, the remaining 3 channels absorb traffic with minimal RT impact
188+ * (compared to {@code N=2} which would double the load on the surviving channel);</li>
189+ * <li>Resource cost stays bounded: 4 fd × ephemeral ports × ~16KB Netty buffer per
190+ * peer is negligible even with hundreds of peer addresses.</li>
191+ * </ul>
192+ *
193+ * <p>Tuning guidance (override per-{@code BackendConfig} via {@code connsPerAddr}):</p>
194+ * <ul>
195+ * <li>Low QPS / few peers: {@code 1~2} (saves resources);</li>
196+ * <li>High QPS / few peers: {@code 8~16} (more EventLoop parallelism);</li>
197+ * <li>Many peer IPs (hundreds+): leave at {@code 4}, the IP fan-out already
198+ * provides parallelism & failure isolation;</li>
199+ * <li>Gateway / aggregation services: {@code 8}.</li>
200+ * </ul>
201+ *
202+ * <p><b>Compatibility note</b>: this default was {@code 2} in earlier versions. Upgrades
203+ * will see <b>per-peer inbound connections double</b> on the server side; review server
204+ * fd ulimits and LB per-source connection limits before rollout.</p>
205+ */
206+ public static final String DEFAULT_CONNECTIONS_PERADDR = "4" ;
162207 public static final String DEFAULT_TRANSPORTER = TRANSPORTER_NETTY ;
163208 public static final String DEFAULT_IO_MODE = IO_MODE_EPOLL ;
164209 /**
0 commit comments