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.sync.extension.TestClientResources;
39 import org.apache.hc.core5.http.HttpHost;
40 import org.apache.hc.core5.http.URIScheme;
41 import org.apache.hc.core5.http.io.entity.EntityUtils;
42 import org.apache.hc.core5.testing.classic.ClassicTestServer;
43 import org.apache.hc.core5.util.TimeValue;
44 import org.apache.hc.core5.util.Timeout;
45 import org.junit.jupiter.api.Test;
46 import org.junit.jupiter.api.extension.RegisterExtension;
47
48 public class TestIdleConnectionEviction {
49
50 public static final Timeout TIMEOUT = Timeout.ofMinutes(1);
51
52 @RegisterExtension
53 private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT);
54
55 @Test
56 public void testIdleConnectionEviction() throws Exception {
57 final ClassicTestServer server = testResources.startServer(null, null, null);
58 server.registerHandler("/random/*", new RandomHandler());
59 final HttpHost target = testResources.targetHost();
60
61 final CloseableHttpClient client = testResources.startClient(b -> {});
62
63 final PoolingHttpClientConnectionManager connManager = testResources.connManager();
64
65 connManager.setDefaultMaxPerRoute(10);
66 connManager.setMaxTotal(50);
67
68 final IdleConnectionEvictor idleConnectionMonitor = new IdleConnectionEvictor(connManager, TimeValue.ofMilliseconds(50));
69 idleConnectionMonitor.start();
70
71 final URI requestUri = new URI("/random/1024");
72 final WorkerThread[] workers = new WorkerThread[5];
73 for (int i = 0; i < workers.length; i++) {
74 workers[i] = new WorkerThread(client, target, requestUri, 200);
75 }
76 for (final WorkerThread worker : workers) {
77 worker.start();
78 }
79 for (final WorkerThread worker : workers) {
80 worker.join();
81 final Exception ex = worker.getException();
82 if (ex != null) {
83 throw ex;
84 }
85 }
86 idleConnectionMonitor.shutdown();
87 }
88
89 static class WorkerThread extends Thread {
90
91 private final CloseableHttpClient httpclient;
92 private final HttpHost target;
93 private final URI requestUri;
94 private final int count;
95
96 private volatile Exception ex;
97
98 public WorkerThread(
99 final CloseableHttpClient httpclient,
100 final HttpHost target,
101 final URI requestUri,
102 final int count) {
103 super();
104 this.httpclient = httpclient;
105 this.target = target;
106 this.requestUri = requestUri;
107 this.count = count;
108 }
109
110 @Override
111 public void run() {
112 try {
113 for (int i = 0; i < this.count; i++) {
114 final HttpGet httpget = new HttpGet(this.requestUri);
115 this.httpclient.execute(this.target, httpget, response -> {
116 final int status = response.getCode();
117 if (status != 200) {
118 throw new ClientProtocolException("Unexpected status code: " + status);
119 }
120 EntityUtils.consume(response.getEntity());
121 try {
122 Thread.sleep(10);
123 } catch (final InterruptedException ex) {
124 Thread.currentThread().interrupt();
125 }
126 return null;
127 });
128 }
129 } catch (final Exception ex) {
130 this.ex = ex;
131 }
132 }
133
134 public Exception getException() {
135 return ex;
136 }
137
138 }
139
140 }