Skip to content

[FeignClientFactoryBean] Potential resource exhaustion risk due to implicit Client creation (RCTP Anti-pattern) #1308

@QiuYucheng2003

Description

@QiuYucheng2003

Describe the bug
I am conducting a research project on Java static analysis, specifically focusing on the "Repeatedly Create Thread Pool" (RCTP) anti-pattern.

During the analysis of org.springframework.cloud.openfeign.FeignClientFactoryBean, I identified a potential performance and resource risk concerning how the underlying Client (which typically holds a connection pool) is resolved.

In the getTarget() method, the factory resolves the Client from the FeignClientFactory context. If the FeignClientFactory (the context) fails to cache the Client bean correctly, or if FeignClientFactoryBean is used in a scope where it is repeatedly re-created (e.g., dynamic proxy creation with changing contextIds), calling getTarget() leads to the creation/resolution of multiple independent Client instances.

This behavior aligns with the RCTP pattern, where heavy resources are instantiated per-request or per-call instead of being shared. While the default behavior relies on Singleton beans, the lack of defensive checks here poses a risk of connection pool exhaustion if the context is misconfigured.

Sample
Since this is a static analysis finding, I provide the code trace analysis instead of a runnable repository.

The issue lies in FeignClientFactoryBean.java:

// Logic in getTarget()
<T> T getTarget() {
    FeignClientFactory feignClientFactory = beanFactory != null ? beanFactory.getBean(FeignClientFactory.class)
            : applicationContext.getBean(FeignClientFactory.class);
    Feign.Builder builder = feign(feignClientFactory);

    // ... 
    
    // Critical Point: Relying on context.getInstance()
    Client client = getOptional(feignClientFactory, Client.class); 
    if (client != null) {
        if (client instanceof FeignBlockingLoadBalancerClient) {
             client = ((FeignBlockingLoadBalancerClient) client).getDelegate();
        }
        builder.client(client);
    }
    
    // ...
}


Suggestion:
1. Guardrail: Consider adding a debug/warn log if getTarget() is called unusually frequently for the same name to alert developers of potential misconfiguration.
2. Documentation: Explicitly document that custom Client beans provided by the context MUST be Singletons to avoid thread/connection leaks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions