-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Description
In 6.1.9, since commit 7785f94 (related issue: #32945), this.httpClient
is no longer assigned. The assignment should probably have happened here:
Lines 128 to 131 in 5356a1b
if (httpClient == null) { | |
Assert.state(this.resourceFactory != null && this.mapper != null, "Illegal configuration"); | |
httpClient = createHttpClient(this.resourceFactory, this.mapper); | |
} |
As a consequence, a new HttpClient
instance is created for every request. Apart from the possible performance impact, this is causing a memory leak in my application: I'm using client certificate authentication configured through Boot's SslBundle
support. This causes the creation of new SslContext
instances alongside each new HttpClient
in org.springframework.boot.autoconfigure.web.reactive.function.client.ReactorClientHttpConnectorFactory
.
Then, because Netty's SslContext
implementations don't implement hashCode()
, Reactor Netty's connection pooling doesn't work properly, causing new HTTP connection pools to be created for every request (config.channelHash()
returns distinct values for every request https://github.com/reactor/reactor-netty/blob/v1.1.20/reactor-netty-core/src/main/java/reactor/netty/resources/PooledConnectionProvider.java#L127-L133).
All these connection pools are then never disposed of (this is Reactor Netty's default configuration I believe), eventually causing an OOME.
TL;DR
- Reactor Netty creates a new HTTP connection pool for every HTTP request, because
- it includes the hash code of Netty's
SslContext
in the pool key, because - an
SslContext
has been configured by Spring Boot'sSslBundle
feature for every request, because - Spring Framework creates new
HttpClient
instances for every request.
The leak itself may be fixed in Netty (should SslContext
implementations have stable hash codes?), but it was surfaced by the commit in Spring Framework.