or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdconnection-pooling.mdcontent-management.mdhttp-operations.mdindex.mdproxy-configuration.mdrequest-configuration.mdresponse-processing.md

connection-pooling.mddocs/

0

# Connection Pooling

1

2

The connection pooling capability provides multiple connection pool strategies for optimizing connection reuse and performance, including duplex, multiplex, round-robin, and random selection pools with comprehensive connection lifecycle management.

3

4

## ConnectionPool Interface

5

6

The base interface for all connection pool implementations.

7

8

```java { .api }

9

public interface ConnectionPool extends Closeable {

10

// Connection acquisition and release

11

CompletableFuture<Connection> acquire(boolean create);

12

boolean release(Connection connection);

13

boolean remove(Connection connection);

14

15

// Pool management

16

void close();

17

boolean isClosed();

18

19

// Pool statistics

20

int getConnectionCount();

21

int getIdleConnectionCount();

22

int getActiveConnectionCount();

23

24

// Pool configuration

25

int getMaxConnectionCount();

26

27

// Preconnection

28

CompletableFuture<Void> preCreateConnections(int connectionCount);

29

}

30

```

31

32

## DuplexConnectionPool

33

34

Connection pool for HTTP/1.1 duplex connections where each connection can handle one request at a time.

35

36

### DuplexConnectionPool Class

37

38

```java { .api }

39

public class DuplexConnectionPool extends AbstractConnectionPool {

40

public DuplexConnectionPool(Destination destination, int maxConnections, Callback requester);

41

public DuplexConnectionPool(Destination destination, int maxConnections, boolean cache, Callback requester);

42

43

// Configuration

44

public boolean isCache();

45

public int getMaxDuplexCount();

46

}

47

```

48

49

### Usage Examples

50

51

```java

52

// Configure HttpClient with duplex connection pool

53

HttpClient client = new HttpClient();

54

client.start();

55

56

// Default connection pool settings

57

// - Max connections per destination: typically 64

58

// - Connection caching: enabled

59

// - Suitable for HTTP/1.1 connections

60

61

// Make concurrent requests - each uses separate connection

62

List<CompletableFuture<ContentResponse>> futures = new ArrayList<>();

63

for (int i = 0; i < 10; i++) {

64

CompletableFuture<ContentResponse> future = client.newRequest("https://api.example.com/data/" + i).send();

65

futures.add(future);

66

}

67

68

// Wait for all requests to complete

69

CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))

70

.thenRun(() -> {

71

System.out.println("All requests completed");

72

futures.forEach(future -> {

73

try {

74

ContentResponse response = future.get();

75

System.out.println("Response: " + response.getStatus());

76

} catch (Exception e) {

77

System.err.println("Request failed: " + e.getMessage());

78

}

79

});

80

});

81

```

82

83

## MultiplexConnectionPool

84

85

Connection pool for HTTP/2 multiplex connections where each connection can handle multiple concurrent requests.

86

87

### MultiplexConnectionPool Class

88

89

```java { .api }

90

public class MultiplexConnectionPool extends AbstractConnectionPool {

91

public MultiplexConnectionPool(Destination destination, int maxConnections, Callback requester, int maxMultiplex);

92

93

// Configuration

94

public int getMaxMultiplex();

95

}

96

```

97

98

### Usage Examples

99

100

```java

101

// Configure HttpClient for HTTP/2 with multiplex connection pool

102

HttpClient client = new HttpClient();

103

104

// Enable HTTP/2

105

client.setProtocols(List.of("h2", "http/1.1"));

106

client.start();

107

108

// HTTP/2 connections can multiplex many requests over single connection

109

// Default max multiplex: typically 1024 streams per connection

110

111

// Make many concurrent requests over fewer connections

112

List<CompletableFuture<ContentResponse>> futures = new ArrayList<>();

113

for (int i = 0; i < 100; i++) {

114

CompletableFuture<ContentResponse> future = client.newRequest("https://http2.example.com/api/data/" + i).send();

115

futures.add(future);

116

}

117

118

// All requests may use the same HTTP/2 connection with multiplexing

119

CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))

120

.thenRun(() -> System.out.println("All HTTP/2 requests completed"));

121

```

122

123

## RoundRobinConnectionPool

124

125

Connection pool that distributes requests across available connections in round-robin fashion.

126

127

### RoundRobinConnectionPool Class

128

129

```java { .api }

130

public class RoundRobinConnectionPool extends AbstractConnectionPool {

131

public RoundRobinConnectionPool(Destination destination, int maxConnections, Callback requester);

132

public RoundRobinConnectionPool(Destination destination, int maxConnections, Callback requester, int maxMultiplex);

133

}

134

```

135

136

### Usage Examples

137

138

```java

139

// Round-robin is useful for load balancing across multiple connections

140

// Typically used with HTTP/1.1 where you want to distribute load evenly

141

142

public class RoundRobinClient {

143

private final HttpClient client;

144

145

public RoundRobinClient() throws Exception {

146

this.client = new HttpClient();

147

148

// Configure connection factory to use round-robin pool

149

// Note: Direct pool configuration is typically done at transport level

150

151

client.start();

152

}

153

154

public void makeBalancedRequests() throws Exception {

155

// Make requests that will be distributed round-robin across connections

156

for (int i = 0; i < 20; i++) {

157

final int requestId = i;

158

client.newRequest("https://api.example.com/endpoint/" + i)

159

.send(result -> {

160

if (result.isSucceeded()) {

161

System.out.println("Request " + requestId + " completed on connection: " +

162

result.getRequest().getConnection());

163

}

164

});

165

}

166

}

167

}

168

```

169

170

## RandomConnectionPool

171

172

Connection pool that randomly selects from available connections.

173

174

### RandomConnectionPool Class

175

176

```java { .api }

177

public class RandomConnectionPool extends AbstractConnectionPool {

178

public RandomConnectionPool(Destination destination, int maxConnections, Callback requester);

179

public RandomConnectionPool(Destination destination, int maxConnections, Callback requester, int maxMultiplex);

180

}

181

```

182

183

### Usage Examples

184

185

```java

186

// Random selection can help avoid hot-spotting on specific connections

187

// Useful when you want to distribute load unpredictably

188

189

public class RandomizedLoadClient {

190

public void demonstrateRandomPool() {

191

// Random connection selection helps with:

192

// - Avoiding connection hot-spots

193

// - Better distribution in some network topologies

194

// - Testing resilience across different connections

195

196

// Requests will be randomly distributed across available connections

197

for (int i = 0; i < 50; i++) {

198

client.GET("https://distributed.example.com/api/data");

199

}

200

}

201

}

202

```

203

204

## ValidatingConnectionPool

205

206

Connection pool that validates connections before use to ensure they are still functional.

207

208

### ValidatingConnectionPool Class

209

210

```java { .api }

211

public class ValidatingConnectionPool extends DuplexConnectionPool {

212

public ValidatingConnectionPool(Destination destination, int maxConnections, Callback requester);

213

214

// Validation configuration

215

public void setValidationTimeout(long validationTimeout);

216

public long getValidationTimeout();

217

}

218

```

219

220

### Usage Examples

221

222

```java

223

// Validating pool is useful for long-lived connections that might become stale

224

// Automatically validates connections before reuse

225

226

public class ValidatedClient {

227

public void configureValidation() throws Exception {

228

HttpClient client = new HttpClient();

229

230

// Configuration for connection validation

231

// Validates connections that have been idle for a certain period

232

client.setIdleTimeout(30000); // 30 seconds idle timeout

233

234

client.start();

235

236

// Long pause between requests to demonstrate validation

237

ContentResponse response1 = client.GET("https://api.example.com/data");

238

System.out.println("First request: " + response1.getStatus());

239

240

// Wait longer than idle timeout

241

Thread.sleep(35000);

242

243

// Next request will validate/recreate connection if needed

244

ContentResponse response2 = client.GET("https://api.example.com/data");

245

System.out.println("Second request: " + response2.getStatus());

246

247

client.stop();

248

}

249

}

250

```

251

252

## Connection Pool Configuration

253

254

### Per-Destination Pool Settings

255

256

```java

257

public class PoolConfigurationExample {

258

public void configureConnectionPools() throws Exception {

259

HttpClient client = new HttpClient();

260

261

// Configure maximum connections per destination

262

client.setMaxConnectionsPerDestination(20);

263

264

// Configure request queue size per destination

265

client.setMaxRequestsQueuedPerDestination(50);

266

267

// Configure connection idle timeout

268

client.setIdleTimeout(60000); // 60 seconds

269

270

// Configure connection establishment timeout

271

client.setConnectTimeout(10000); // 10 seconds

272

273

client.start();

274

275

// These settings affect all connection pools for this client

276

System.out.println("Max connections per destination: " + client.getMaxConnectionsPerDestination());

277

System.out.println("Idle timeout: " + client.getIdleTimeout());

278

}

279

}

280

```

281

282

### Custom Connection Pool Factory

283

284

```java

285

public class CustomConnectionPoolFactory {

286

public static ConnectionPool createCustomPool(Destination destination, int maxConnections) {

287

// Create a custom connection pool based on requirements

288

289

if (destination.getScheme().equals("https") && supportsHttp2(destination)) {

290

// Use multiplex pool for HTTP/2 HTTPS connections

291

return new MultiplexConnectionPool(destination, maxConnections, null, 100);

292

} else if (isHighVolumeDestination(destination)) {

293

// Use round-robin for high-volume destinations

294

return new RoundRobinConnectionPool(destination, maxConnections, null);

295

} else if (isUnreliableNetwork(destination)) {

296

// Use validating pool for unreliable networks

297

return new ValidatingConnectionPool(destination, maxConnections, null);

298

} else {

299

// Default to duplex pool

300

return new DuplexConnectionPool(destination, maxConnections, null);

301

}

302

}

303

304

private static boolean supportsHttp2(Destination destination) {

305

// Logic to determine if destination supports HTTP/2

306

return true; // Simplified

307

}

308

309

private static boolean isHighVolumeDestination(Destination destination) {

310

// Logic to identify high-volume destinations

311

return destination.getHost().contains("api") || destination.getHost().contains("cdn");

312

}

313

314

private static boolean isUnreliableNetwork(Destination destination) {

315

// Logic to identify destinations with unreliable connections

316

return destination.getHost().contains("mobile") || destination.getHost().contains("satellite");

317

}

318

}

319

```

320

321

## Connection Pool Monitoring

322

323

### Pool Statistics

324

325

```java

326

public class ConnectionPoolMonitor {

327

private final HttpClient client;

328

329

public ConnectionPoolMonitor(HttpClient client) {

330

this.client = client;

331

}

332

333

public void printPoolStatistics() {

334

// Note: Direct access to connection pools requires internal APIs

335

// This is conceptual - actual implementation may vary

336

337

System.out.println("Connection Pool Statistics:");

338

System.out.println("Max connections per destination: " + client.getMaxConnectionsPerDestination());

339

System.out.println("Current destinations: " + getDestinationCount());

340

341

// Per-destination statistics would require accessing internal destination manager

342

printDestinationStats();

343

}

344

345

private void printDestinationStats() {

346

// Conceptual implementation for monitoring

347

System.out.println("Destination Statistics:");

348

System.out.println(" api.example.com: 5 active, 3 idle connections");

349

System.out.println(" cdn.example.com: 2 active, 8 idle connections");

350

}

351

352

private int getDestinationCount() {

353

// Would access internal destination manager

354

return 0; // Placeholder

355

}

356

357

public void scheduleMonitoring(ScheduledExecutorService scheduler) {

358

scheduler.scheduleAtFixedRate(this::printPoolStatistics, 0, 30, TimeUnit.SECONDS);

359

}

360

}

361

```

362

363

### Connection Lifecycle Monitoring

364

365

```java

366

public class ConnectionLifecycleMonitor {

367

public void monitorConnections(HttpClient client) {

368

// Add request listeners to monitor connection usage

369

client.getRequestListeners().addListener(new Request.Listener() {

370

@Override

371

public void onBegin(Request request) {

372

Connection connection = request.getConnection();

373

if (connection != null) {

374

System.out.println("Request started on connection: " + connection);

375

}

376

}

377

378

@Override

379

public void onSuccess(Request request) {

380

Connection connection = request.getConnection();

381

if (connection != null) {

382

System.out.println("Request completed on connection: " + connection);

383

}

384

}

385

});

386

}

387

}

388

```

389

390

## Advanced Pool Management

391

392

### Pool Preheating

393

394

```java

395

public class PoolPreheating {

396

public void preheatConnections(HttpClient client, String... urls) throws Exception {

397

List<CompletableFuture<Void>> preheatFutures = new ArrayList<>();

398

399

for (String url : urls) {

400

// Make lightweight requests to establish connections

401

CompletableFuture<Void> future = client.newRequest(url)

402

.method(HttpMethod.HEAD) // Use HEAD to minimize data transfer

403

.send()

404

.thenApply(response -> null); // Convert to Void

405

406

preheatFutures.add(future);

407

}

408

409

// Wait for all preheat requests to complete

410

CompletableFuture.allOf(preheatFutures.toArray(new CompletableFuture[0]))

411

.get(30, TimeUnit.SECONDS);

412

413

System.out.println("Connection pools preheated for " + urls.length + " destinations");

414

}

415

}

416

417

// Usage

418

PoolPreheating preheater = new PoolPreheating();

419

preheater.preheatConnections(client,

420

"https://api.example.com",

421

"https://cdn.example.com",

422

"https://auth.example.com"

423

);

424

```

425

426

### Dynamic Pool Sizing

427

428

```java

429

public class DynamicPoolManager {

430

private final HttpClient client;

431

private final Map<String, Integer> destinationLoad;

432

433

public DynamicPoolManager(HttpClient client) {

434

this.client = client;

435

this.destinationLoad = new ConcurrentHashMap<>();

436

}

437

438

public void adjustPoolSizes() {

439

destinationLoad.forEach((destination, load) -> {

440

int recommendedSize = calculateOptimalPoolSize(load);

441

adjustPoolSize(destination, recommendedSize);

442

});

443

}

444

445

private int calculateOptimalPoolSize(int load) {

446

// Calculate optimal pool size based on load

447

if (load > 100) return 50;

448

if (load > 50) return 25;

449

if (load > 10) return 10;

450

return 5;

451

}

452

453

private void adjustPoolSize(String destination, int size) {

454

// Conceptual - actual implementation would require internal APIs

455

System.out.println("Adjusting pool size for " + destination + " to " + size);

456

}

457

458

public void recordRequest(String destination) {

459

destinationLoad.merge(destination, 1, Integer::sum);

460

}

461

462

public void scheduleOptimization(ScheduledExecutorService scheduler) {

463

scheduler.scheduleAtFixedRate(this::adjustPoolSizes, 0, 60, TimeUnit.SECONDS);

464

}

465

}

466

```

467

468

## Connection Pool Best Practices

469

470

### Optimal Configuration

471

472

```java

473

public class PoolBestPractices {

474

public HttpClient createOptimalClient() throws Exception {

475

HttpClient client = new HttpClient();

476

477

// Conservative connection limits to avoid overwhelming servers

478

client.setMaxConnectionsPerDestination(20);

479

client.setMaxRequestsQueuedPerDestination(100);

480

481

// Reasonable timeouts

482

client.setConnectTimeout(10000); // 10 seconds

483

client.setIdleTimeout(60000); // 60 seconds

484

485

// Enable connection keep-alive

486

client.setTCPNoDelay(true);

487

488

// Configure for HTTP/2 when available

489

client.setProtocols(List.of("h2", "http/1.1"));

490

491

client.start();

492

return client;

493

}

494

495

public void demonstrateEfficientUsage(HttpClient client) throws Exception {

496

// Reuse client across multiple requests for connection pooling benefits

497

List<CompletableFuture<ContentResponse>> futures = new ArrayList<>();

498

499

// Make multiple requests to same destination - will reuse connections

500

for (int i = 0; i < 10; i++) {

501

CompletableFuture<ContentResponse> future = client.newRequest("https://api.example.com/data/" + i).send();

502

futures.add(future);

503

}

504

505

// Process responses as they complete

506

for (CompletableFuture<ContentResponse> future : futures) {

507

future.thenAccept(response -> {

508

System.out.println("Response: " + response.getStatus());

509

// Connection automatically returned to pool after response processing

510

});

511

}

512

513

// Don't stop client until all operations are complete

514

CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

515

}

516

}

517

```

518

519

### Resource Management

520

521

```java

522

public class ResourceManagedClient implements AutoCloseable {

523

private final HttpClient client;

524

525

public ResourceManagedClient() throws Exception {

526

this.client = new HttpClient();

527

configureClient();

528

client.start();

529

}

530

531

private void configureClient() {

532

// Optimize for connection reuse

533

client.setMaxConnectionsPerDestination(15);

534

client.setIdleTimeout(30000);

535

536

// Add shutdown hook for graceful cleanup

537

Runtime.getRuntime().addShutdownHook(new Thread(() -> {

538

try {

539

close();

540

} catch (Exception e) {

541

System.err.println("Error during client shutdown: " + e.getMessage());

542

}

543

}));

544

}

545

546

public ContentResponse get(String url) throws Exception {

547

return client.GET(url);

548

}

549

550

@Override

551

public void close() throws Exception {

552

// Graceful shutdown - allows existing requests to complete

553

client.stop();

554

}

555

}

556

557

// Usage with try-with-resources

558

try (ResourceManagedClient client = new ResourceManagedClient()) {

559

ContentResponse response = client.get("https://api.example.com/data");

560

System.out.println("Response: " + response.getStatus());

561

} // Automatically closes and cleans up connection pools

562

```