Skip to content

Commit 5e91441

Browse files
authored
Http2Client: added clients cache (#2405)
1 parent 181bd05 commit 5e91441

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

java11/src/main/java/feign/http2client/Http2Client.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import java.io.ByteArrayInputStream;
1717
import java.io.IOException;
18+
import java.lang.ref.SoftReference;
1819
import java.net.URI;
1920
import java.net.URISyntaxException;
2021
import java.net.http.HttpClient;
@@ -39,6 +40,7 @@
3940
import java.util.Set;
4041
import java.util.TreeSet;
4142
import java.util.concurrent.CompletableFuture;
43+
import java.util.concurrent.ConcurrentHashMap;
4244
import java.util.function.Function;
4345
import java.util.stream.Collectors;
4446
import feign.AsyncClient;
@@ -54,6 +56,8 @@ public class Http2Client implements Client, AsyncClient<Object> {
5456

5557
private final HttpClient client;
5658

59+
private final Map<Integer, SoftReference<HttpClient>> clients = new ConcurrentHashMap<>();
60+
5761
/**
5862
* Creates the new Http2Client using following defaults:
5963
* <ul>
@@ -140,15 +144,24 @@ private HttpClient getOrCreateClient(Options options) {
140144
if (doesClientConfigurationDiffer(options)) {
141145
// create a new client from the existing one - but with connectTimeout and followRedirect
142146
// settings from options
143-
java.net.http.HttpClient.Builder builder = newClientBuilder(options)
144-
.sslContext(client.sslContext())
145-
.sslParameters(client.sslParameters())
146-
.version(client.version());
147-
client.authenticator().ifPresent(builder::authenticator);
148-
client.cookieHandler().ifPresent(builder::cookieHandler);
149-
client.executor().ifPresent(builder::executor);
150-
client.proxy().ifPresent(builder::proxy);
151-
return builder.build();
147+
final int clientKey = createClientKey(options);
148+
149+
SoftReference<HttpClient> requestScopedSoftReference = clients.get(clientKey);
150+
HttpClient requestScoped = requestScopedSoftReference == null ? null : requestScopedSoftReference.get();
151+
152+
if (requestScoped == null) {
153+
java.net.http.HttpClient.Builder builder = newClientBuilder(options)
154+
.sslContext(client.sslContext())
155+
.sslParameters(client.sslParameters())
156+
.version(client.version());
157+
client.authenticator().ifPresent(builder::authenticator);
158+
client.cookieHandler().ifPresent(builder::cookieHandler);
159+
client.executor().ifPresent(builder::executor);
160+
client.proxy().ifPresent(builder::proxy);
161+
requestScoped = builder.build();
162+
clients.put(clientKey, new SoftReference<>(requestScoped));
163+
}
164+
return requestScoped;
152165
}
153166
return client;
154167
}
@@ -162,6 +175,20 @@ private boolean doesClientConfigurationDiffer(Options options) {
162175
.orElse(true);
163176
}
164177

178+
/**
179+
* Creates integer key that represents {@link Options} settings based
180+
* on {@link Http2Client#doesClientConfigurationDiffer(Options)} method
181+
* @param options value
182+
* @return integer key
183+
*/
184+
public int createClientKey(feign.Request.Options options) {
185+
int key = options.connectTimeoutMillis();
186+
if (options.isFollowRedirects()) {
187+
key |= 1 << 31; // connectTimeoutMillis always positive, so we can use first sign bit for isFollowRedirects flag
188+
}
189+
return key;
190+
}
191+
165192
private static java.net.http.HttpClient.Builder newClientBuilder(Options options) {
166193
return HttpClient
167194
.newBuilder()

0 commit comments

Comments
 (0)