内存泄漏,弹簧3.2.0.RELEASE,httpcomponents 4.2.3 [英] Memory leak, spring 3.2.0.RELEASE, httpcomponents 4.2.3

查看:191
本文介绍了内存泄漏,弹簧3.2.0.RELEASE,httpcomponents 4.2.3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用spring 3.2.0.RELEASE resttemplate& httpcomponents 4.2.3进行休息调用。内存占用量稳步增长,直到达到最大值。

Using spring 3.2.0.RELEASE resttemplate & httpcomponents 4.2.3 to make rest calls. Memory footprint is steadily increasing until it reaches max.

以下是配置:

<bean id="myRestTemplate" class="org.springframework.web.client.RestTemplate">
    <constructor-arg>
        <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
            <constructor-arg index="0">
                <bean factory-bean="httpClient" factory-method="get"/>
            </constructor-arg>
        </bean>
    </constructor-arg>
</bean>
<bean id="httpClient" class="com.mycompany.myproject.common.rest.HttpClient">
    <constructor-arg index="0" ref="myKeyserverCA" ></constructor-arg>
    <constructor-arg index="1" value="${com.mycompany.myproject.security.client.keyPassword}" ></constructor-arg>
    <constructor-arg index="2" value="${default.max.total.connections}" ></constructor-arg>
    <constructor-arg index="3" value="${default.max.host.connections}" ></constructor-arg>
</bean>
<bean id="myKeyserverCA"
      class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
    <property name="location" value="classpath:${com.mycompany.myproject.security.client.keyStore}" />
    <property name="password" value="${com.mycompany.myproject.security.client.keyStorePass}" />
</bean>    

HttpClient:

HttpClient:

import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.CoreConnectionPNames;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.security.KeyStore;

public class HttpClient {

private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);

private KeyStore keystore;
private String password;
private int MAX_TOTAL_CONNECTION;
private int MAX_PER_ROUTE;

public HttpClient(KeyStore keyStore, String keyPassword, int MAX_TOTAL_CONNECTION, int MAX_PER_ROUTE) {
    this.keystore = keyStore;
    this.password = keyPassword;
    this.MAX_TOTAL_CONNECTION = MAX_TOTAL_CONNECTION;
    this.MAX_PER_ROUTE = MAX_PER_ROUTE;
}

public org.apache.http.client.HttpClient get() {
    PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(getSchemeRegistry(this.keystore, this.password));
    connectionManager.setMaxTotal(MAX_TOTAL_CONNECTION);
    connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
    connectionManager.closeExpiredConnections();

    org.apache.http.client.HttpClient httpClient = new DefaultHttpClient(connectionManager);
    httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, DEFAULT_READ_TIMEOUT_MILLISECONDS);
    return httpClient;
}

private static SchemeRegistry getSchemeRegistry(KeyStore keyStore, String keyPassword) {
    SchemeRegistry registry = new SchemeRegistry();
    try{
        TrustManager[] trustManagerArray = { new TautologicalX509TrustManager() };
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, keyPassword.toCharArray());

        SSLContext sslc = SSLContext.getInstance("TLS");
        sslc.init(kmf.getKeyManagers(), trustManagerArray, null);
                    SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslc, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                    registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
        registry.register(new Scheme("https", 443, sslSocketFactory));
        return registry;
    }catch(Exception e){
        throw new RuntimeException(e.getMessage());
    }
}
}    

TautologicalX509TrustManager:

TautologicalX509TrustManager:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class TautologicalX509TrustManager  implements X509TrustManager {

private static final X509Certificate[] EMPTY_CERTIFICATES = new X509Certificate [0];

public void checkClientTrusted(X509Certificate[] arg0, String arg1)
    throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] arg0, String arg1)
        throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
    return EMPTY_CERTIFICATES;
}



}    

在对此组件运行负载测试后,我们看到很多SSLSocketImpl对象和byte []。
对SSLSocketImpl的传入引用来自Finalizer对象。

After running load tests on this component, we see lot of SSLSocketImpl objects and byte[]. Incoming references to SSLSocketImpl are from Finalizer object.

当我们在加载测试停止后在机器上执行netstat时,我们没有看到任何打开到底层的tcp连接服务。然而,在负载测试期间,有许多处于TIME_WAIT状态的连接,很少处于ESTABLISHED状态,但是在测试停止后它们都被关闭。

When we do netstat on the machine after load test is stopped, we dont see any open tcp connections to underlying services. During the load test however, there are many many connections in TIME_WAIT state and few in ESTABLISHED state but all of them are closed after test is stopped.

我们是否缺少任何API打电话给关闭套接字?为什么我们堆中有这么多SSLSocketImpl对象?

Are we missing any API call to close sockets? Why do we have so many SSLSocketImpl objects hanging around in our heap?

推荐答案

有点迟到的回复但这个答案是为了以后的访问者这个问题。您在堆中看到大量 SSLSocketImpl 然后收集垃圾的原因是因为 SSLSessionContext 支持缓存SSL连接,可以跨不同的TCP连接重用,以减少在建立实际TCP连接后协商临时加密密钥时的握手开销。

Bit late reply but this answer is for future visitors to this question. The reason that you see large volume of SSLSocketImpl in your heap and then which gets garbage collected is because SSLSessionContext supports caching SSL connections, which can be reused by across distinct TCP connections to reduce handshake overhead when negotiating temporary encryption keys after the actual TCP connection has been established.

默认情况下 SSLSessionContext 默认时间为24小时的无限会话数,这意味着您可以在高流量下使用大量堆内存。一种方法是设置适合您的应用程序需求的缓存大小。下面是一个示例:

By default the SSLSessionContext unlimited number of sessions for default time period of 24 hours, which means that you can end up using lot of heap memory under high traffic. One way is to set cache size that suits your application needs. Here is an example:

sslContext.getServerSessionContext()。setSessionCacheSize(1000);

这篇关于内存泄漏,弹簧3.2.0.RELEASE,httpcomponents 4.2.3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆