|
28 | 28 |
|
29 | 29 | import java.io.IOException; |
30 | 30 | import java.net.URISyntaxException; |
| 31 | +import java.util.concurrent.locks.ReentrantLock; |
31 | 32 |
|
32 | 33 | import org.apache.hc.client5.http.auth.AuthCache; |
33 | 34 | import org.apache.hc.client5.http.auth.AuthScope; |
|
36 | 37 | import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; |
37 | 38 | import org.apache.hc.client5.http.config.ConnectionConfig; |
38 | 39 | import org.apache.hc.client5.http.cookie.CookieStore; |
| 40 | +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; |
| 41 | +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; |
39 | 42 | import org.apache.hc.client5.http.impl.auth.BasicAuthCache; |
40 | 43 | import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; |
41 | 44 | import org.apache.hc.client5.http.impl.auth.BasicScheme; |
42 | 45 | import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; |
43 | 46 | import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; |
| 47 | +import org.apache.hc.client5.http.impl.compat.ClassicToAsyncAdaptor; |
44 | 48 | import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; |
| 49 | +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; |
45 | 50 | import org.apache.hc.client5.http.protocol.HttpClientContext; |
| 51 | +import org.apache.hc.core5.annotation.Experimental; |
46 | 52 | import org.apache.hc.core5.http.HttpHost; |
47 | 53 | import org.apache.hc.core5.util.TimeValue; |
| 54 | +import org.apache.hc.core5.util.Timeout; |
48 | 55 |
|
49 | 56 | /** |
50 | 57 | * Executor for {@link Request}s. |
|
56 | 63 | */ |
57 | 64 | public class Executor { |
58 | 65 |
|
59 | | - final static CloseableHttpClient CLIENT; |
| 66 | + private static final ReentrantLock LOCK = new ReentrantLock(); |
| 67 | + private static volatile CloseableHttpClient CLIENT; |
| 68 | + private static volatile CloseableHttpClient ASYNC_CLIENT; |
60 | 69 |
|
61 | | - static { |
62 | | - CLIENT = HttpClientBuilder.create() |
63 | | - .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create() |
| 70 | + static CloseableHttpClient GET_CLASSIC_CLIENT() { |
| 71 | + final CloseableHttpClient client = CLIENT; |
| 72 | + if (client != null) { |
| 73 | + return client; |
| 74 | + } |
| 75 | + LOCK.lock(); |
| 76 | + try { |
| 77 | + if (CLIENT == null) { |
| 78 | + CLIENT = HttpClientBuilder.create() |
| 79 | + .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create() |
| 80 | + .useSystemProperties() |
| 81 | + .setMaxConnPerRoute(100) |
| 82 | + .setMaxConnTotal(200) |
| 83 | + .setDefaultConnectionConfig(ConnectionConfig.custom() |
| 84 | + .setValidateAfterInactivity(TimeValue.ofSeconds(10)) |
| 85 | + .build()) |
| 86 | + .build()) |
64 | 87 | .useSystemProperties() |
65 | | - .setMaxConnPerRoute(100) |
66 | | - .setMaxConnTotal(200) |
67 | | - .setDefaultConnectionConfig(ConnectionConfig.custom() |
68 | | - .setValidateAfterInactivity(TimeValue.ofSeconds(10)) |
| 88 | + .evictExpiredConnections() |
| 89 | + .evictIdleConnections(TimeValue.ofMinutes(1)) |
| 90 | + .build(); |
| 91 | + } |
| 92 | + return CLIENT; |
| 93 | + } finally { |
| 94 | + LOCK.unlock(); |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + static CloseableHttpClient GET_ASYNC_CLIENT() { |
| 99 | + final CloseableHttpClient client = ASYNC_CLIENT; |
| 100 | + if (client != null) { |
| 101 | + return client; |
| 102 | + } |
| 103 | + LOCK.lock(); |
| 104 | + try { |
| 105 | + if (ASYNC_CLIENT == null) { |
| 106 | + ASYNC_CLIENT = new ClassicToAsyncAdaptor(HttpAsyncClientBuilder.create() |
| 107 | + .setConnectionManager(PoolingAsyncClientConnectionManagerBuilder.create() |
| 108 | + .useSystemProperties() |
| 109 | + .setMaxConnPerRoute(100) |
| 110 | + .setMaxConnTotal(200) |
| 111 | + .setMessageMultiplexing(true) |
| 112 | + .setDefaultConnectionConfig(ConnectionConfig.custom() |
| 113 | + .setValidateAfterInactivity(TimeValue.ofSeconds(10)) |
| 114 | + .build()) |
69 | 115 | .build()) |
70 | | - .build()) |
71 | | - .useSystemProperties() |
72 | | - .evictExpiredConnections() |
73 | | - .evictIdleConnections(TimeValue.ofMinutes(1)) |
74 | | - .build(); |
| 116 | + .useSystemProperties() |
| 117 | + .evictExpiredConnections() |
| 118 | + .evictIdleConnections(TimeValue.ofMinutes(1)) |
| 119 | + .build(), Timeout.ofMinutes(5)); |
| 120 | + } |
| 121 | + return ASYNC_CLIENT; |
| 122 | + } finally { |
| 123 | + LOCK.unlock(); |
| 124 | + } |
75 | 125 | } |
76 | 126 |
|
77 | 127 | public static Executor newInstance() { |
78 | | - return new Executor(CLIENT); |
| 128 | + return new Executor(GET_CLASSIC_CLIENT()); |
79 | 129 | } |
80 | 130 |
|
81 | 131 | public static Executor newInstance(final CloseableHttpClient httpclient) { |
82 | | - return new Executor(httpclient != null ? httpclient : CLIENT); |
| 132 | + return new Executor(httpclient != null ? httpclient : GET_CLASSIC_CLIENT()); |
| 133 | + } |
| 134 | + |
| 135 | + /** |
| 136 | + * This feature is considered experimental and may be discontinued in the future. |
| 137 | + * @since 5.5 |
| 138 | + */ |
| 139 | + @Experimental |
| 140 | + public static Executor newInstance(final CloseableHttpAsyncClient httpclient) { |
| 141 | + return new Executor(httpclient != null ? new ClassicToAsyncAdaptor(httpclient, Timeout.ofMinutes(5)) : GET_ASYNC_CLIENT()); |
83 | 142 | } |
84 | 143 |
|
85 | 144 | private final CloseableHttpClient httpclient; |
|
0 commit comments