由于项目中发送请求的客户端非常多,比如apache的httpclient,也用过hutool的httputil,但是spring5之后都是推荐使用webflux进行请求的发送或处理,所以我们将平常的httpclient去掉,引入了spring-webflux,并自己动手构建了一个webclientutil作为请求发送的客户端。在此期间由于是手动构建的util,或多或少都有可能会写出一些bug,其中我们使用wenclient调用外部互联网接口时,由于对方是https连接,所以请求会失败因为没有安装证书,这时有两个处理方式一个是在spring项目中安装请求接口地址的证书,第二点就是跳过SSL证书验证,于是我们在util中加了一个方法构建一个可信任的证书用于跳过SSL验证,在经过多次请求发现服务器宕机了,打开日志发现是堆内存溢出,经过排除法发现不调用跳过SSL证书的方法就不会导致内存增加。
导致内存溢出的方法
public WebClientUtil trustSSL(){
SslContext sslContext = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
httpClient = httpClient.secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
return this;
}
由于创建SslContext包含静态变量而WebClientUtil又是手动new导致webclientutil不会被回收。
改造
可以通过springboot启动时将其注入为bean即可,保持单例后续直接使用。
创建bean
@Bean
public ConnectionProvider connectionProvider(){
return ConnectionProvider.builder("connection-provider")
// 最大连接数 默认为处理器数量*2
.maxConnections(500)
// 默认等待队列等于maxConnections*2
.pendingAcquireMaxCount(1000)
// 最大空闲时间
.maxIdleTime(Duration.ofSeconds(120))
// 连接最大生命周期
.maxLifeTime(Duration.ofSeconds(60))
.build();
}
改造后的工具方法
public WebClientUtil trustSSL(){
SslContext sslContext = SpringUtil.getBean("sslContext");
httpClient = httpClient.secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
return this;
}