Skip to content

Commit a058941

Browse files
authored
Merge pull request #1360 from gokid96/fix/feign-client-warn-log
Add WARN log and docs for Client bean Singleton requirement
2 parents d92cc04 + 21bacd8 commit a058941

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

docs/modules/ROOT/pages/spring-cloud-openfeign.adoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ Spring Cloud OpenFeign provides the following beans by default for feign (`BeanT
138138
* `Client` feignClient: If Spring Cloud LoadBalancer is on the classpath, `FeignBlockingLoadBalancerClient` is used.
139139
If none of them is on the classpath, the default Feign client is used.
140140

141+
WARNING: The `Client` bean must be configured as a Singleton.
142+
If the `Client` bean is not a Singleton, a new connection pool may be created on each
143+
`FeignClient` initialization, which can lead to connection pool exhaustion and resource leaks.
144+
If you see a warning log about a `FeignClient` with a given `contextId` being initialized
145+
more than once, verify that your custom `Client` bean is Singleton scoped.
146+
141147
NOTE: `spring-cloud-starter-openfeign` supports `spring-cloud-starter-loadbalancer`. However, as is an optional dependency, you need to make sure it has been added to your project if you want to use it.
142148

143149
When it comes to the Apache HttpClient 5-backed Feign clients, it's enough to ensure HttpClient 5 is on the classpath, but you can still disable its use for Feign Clients by setting `spring.cloud.openfeign.httpclient.hc5.enabled` to `false`.

spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactoryBean.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.Collection;
21+
import java.util.Collections;
2122
import java.util.HashMap;
2223
import java.util.List;
2324
import java.util.Map;
2425
import java.util.Objects;
26+
import java.util.Set;
27+
import java.util.concurrent.ConcurrentHashMap;
2528
import java.util.concurrent.TimeUnit;
2629

2730
import feign.Capability;
@@ -85,6 +88,8 @@ public class FeignClientFactoryBean
8588

8689
private static final Log LOG = LogFactory.getLog(FeignClientFactoryBean.class);
8790

91+
private static final Set<String> resolvedContextIds = Collections.newSetFromMap(new ConcurrentHashMap<>());
92+
8893
private Class<?> type;
8994

9095
private String name;
@@ -488,6 +493,14 @@ <T> T getTarget() {
488493
// (e.g., connection pools, threads) if not properly managed.
489494
Client client = getOptional(feignClientFactory, Client.class);
490495
if (client != null) {
496+
if (!resolvedContextIds.add(contextId)) {
497+
if (LOG.isWarnEnabled()) {
498+
LOG.warn("FeignClient with contextId '" + contextId
499+
+ "' is being initialized more than once. "
500+
+ "Ensure the Client bean is Singleton scoped "
501+
+ "to avoid connection pool exhaustion.");
502+
}
503+
}
491504
if (client instanceof FeignBlockingLoadBalancerClient) {
492505
// not load balancing because we have a url,
493506
// but Spring Cloud LoadBalancer is on the classpath, so unwrap

0 commit comments

Comments
 (0)