Spring WebClient 如何避免 Apache HttpClient 5 内存泄漏?
2024-03-30 18:59:15
Spring WebClient 中如何避免 Apache HttpClient 5 内存泄漏
问题:Apache HttpClient 5 内存泄漏
在升级 Spring Boot 应用程序后,我们使用 Spring 的新 WebClient,发现“idle-connection-evictor”线程存在内存泄漏,导致 WebappClassloader 无法 GC。这是由 Apache HttpClient 5(异步)创建的。
原因:缺少资源清理
内存泄漏是由未正确关闭 Apache HttpClient 5 的 CloseableHttpAsyncClient 引起的。Spring WebClient 缺乏关闭机制,导致资源未释放。
解决方案:手动关闭资源
为了避免内存泄漏,需要手动关闭 CloseableHttpAsyncClient。这是通过使用 try-with-resource 语句或显式调用 close() 方法实现的。
此外,HttpComponentsClientHttpConnector 提供了一个 close() 方法来释放资源。确保在不再需要 WebClient 时调用此方法。
最佳实践:使用 Bean 注入
将 HttpComponentsClientHttpConnector 注册为 Bean 是一个最佳做法。这允许在 Bean 生命周期结束时自动关闭它。这可以通过在 Spring 上下文中使用 @Bean 注解实现。
代码更新
以下是更新的代码,已应用上述解决方案:
@Bean
public CloseableHttpAsyncClient httpAsyncClient() {
return HttpAsyncClients.custom()
.setConnectionManager(connManager)
.evictIdleConnections(TimeValue.ofSeconds(60))
.build();
}
@Bean
public HttpComponentsClientHttpConnector clientConnector(CloseableHttpAsyncClient httpAsyncClient) {
return new HttpComponentsClientHttpConnector(httpAsyncClient);
}
public WebClient build() {
final ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
buildOAuth2AuthorizedClientManager());
return WebClient.builder()
.clientConnector(clientConnector)
.apply(oauth2Client.oauth2Configuration())
.build();
}
结论
通过遵循这些步骤,可以避免在 Spring WebClient 中使用 Apache HttpClient 5 造成的内存泄漏。正确关闭资源和使用 Bean 注入有助于确保资源的适当释放和应用程序的稳定运行。
常见问题解答
1. 为什么 Spring WebClient 不提供关闭方法?
Spring WebClient 是一个反应式客户端,设计为无状态的。它不持有对基础连接的引用,因此不提供关闭方法。
2. 我可以使用 try-with-resource 语句来关闭 CloseableHttpAsyncClient 吗?
是的,使用 try-with-resource 语句是一种简单有效的方法,可以确保在代码块执行完成后关闭 CloseableHttpAsyncClient。
3. HttpComponentsClientHttpConnector 是否实现了关闭方法?
是的,HttpComponentsClientHttpConnector 提供了一个 close() 方法来释放资源。在不再需要 WebClient 时调用此方法非常重要。
4. 将 HttpComponentsClientHttpConnector 注册为 Bean 有什么好处?
将 HttpComponentsClientHttpConnector 注册为 Bean 可以确保它在 Bean 生命周期结束时自动关闭。这是一种避免内存泄漏的最佳实践。
5. 除了内存泄漏,还有哪些其他影响?
如果不关闭资源,除了内存泄漏外,还会导致其他问题,例如性能下降和不稳定的应用程序行为。