1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.testing.sync;
29
30 import java.net.URI;
31
32 import org.apache.hc.client5.http.ClientProtocolException;
33 import org.apache.hc.client5.http.classic.methods.HttpGet;
34 import org.apache.hc.client5.http.impl.IdleConnectionEvictor;
35 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
36 import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
37 import org.apache.hc.client5.testing.classic.RandomHandler;
38 import org.apache.hc.client5.testing.extension.sync.ClientProtocolLevel;
39 import org.apache.hc.client5.testing.extension.sync.TestClient;
40 import org.apache.hc.core5.http.HttpHost;
41 import org.apache.hc.core5.http.URIScheme;
42 import org.apache.hc.core5.http.io.entity.EntityUtils;
43 import org.apache.hc.core5.util.TimeValue;
44 import org.junit.jupiter.api.Test;
45
46 class TestIdleConnectionEviction extends AbstractIntegrationTestBase {
47
48 public TestIdleConnectionEviction() {
49 super(URIScheme.HTTP, ClientProtocolLevel.STANDARD);
50 }
51
52 @Test
53 void testIdleConnectionEviction() throws Exception {
54 configureServer(bootstrap -> bootstrap
55 .register("/random/*", new RandomHandler()));
56 final HttpHost target = startServer();
57
58 final TestClient client = client();
59
60 final PoolingHttpClientConnectionManager connManager = client.getConnectionManager();
61
62 connManager.setDefaultMaxPerRoute(10);
63 connManager.setMaxTotal(50);
64
65 final IdleConnectionEvictor idleConnectionMonitor = new IdleConnectionEvictor(connManager, TimeValue.ofMilliseconds(50));
66 idleConnectionMonitor.start();
67
68 final URI requestUri = new URI("/random/1024");
69 final WorkerThread[] workers = new WorkerThread[5];
70 for (int i = 0; i < workers.length; i++) {
71 workers[i] = new WorkerThread(client, target, requestUri, 200);
72 }
73 for (final WorkerThread worker : workers) {
74 worker.start();
75 }
76 for (final WorkerThread worker : workers) {
77 worker.join();
78 final Exception ex = worker.getException();
79 if (ex != null) {
80 throw ex;
81 }
82 }
83 idleConnectionMonitor.shutdown();
84 }
85
86 static class WorkerThread extends Thread {
87
88 private final CloseableHttpClient httpclient;
89 private final HttpHost target;
90 private final URI requestUri;
91 private final int count;
92
93 private volatile Exception ex;
94
95 public WorkerThread(
96 final CloseableHttpClient httpclient,
97 final HttpHost target,
98 final URI requestUri,
99 final int count) {
100 super();
101 this.httpclient = httpclient;
102 this.target = target;
103 this.requestUri = requestUri;
104 this.count = count;
105 }
106
107 @Override
108 public void run() {
109 try {
110 for (int i = 0; i < this.count; i++) {
111 final HttpGet httpget = new HttpGet(this.requestUri);
112 this.httpclient.execute(this.target, httpget, response -> {
113 final int status = response.getCode();
114 if (status != 200) {
115 throw new ClientProtocolException("Unexpected status code: " + status);
116 }
117 EntityUtils.consume(response.getEntity());
118 try {
119 Thread.sleep(10);
120 } catch (final InterruptedException ex) {
121 Thread.currentThread().interrupt();
122 }
123 return null;
124 });
125 }
126 } catch (final Exception ex) {
127 this.ex = ex;
128 }
129 }
130
131 public Exception getException() {
132 return ex;
133 }
134
135 }
136
137 }