• 记录一次大量CLOSE_WAIT的情况


      近期的项目中,有一个特殊的需求,对于每个客户端程序有若干个机构,对于每个机构有不同的客户端证书,程序间隔一段时间向服务端进行请求,根据请求的成功与否更新各机构的状态(如正常,证书未配置,证书过期等)。

      实际投入测试环境进行使用的时候,运行了一段时间之后,客户端程序出现了大量的CLOSE_WAIT的情况,导致压力测试无法正常进行。

      对相关的代码进行了检查之后,发现了之前的做法是对于每一个机构,维护一个RestTemplate对象,在其中进行读取证书等操作。怀疑和大量的restTemplate有关这个问题,因为本地开发的时候基本只有几个机构进行测试,所以未出现以上情况。根据CLOSE_WAIT出现在客户端的情况进行分析,是服务端发起了关闭连接的请求,而客户端进行了响应之后,接收了数据完成后并没有进行关闭,导致出现了CLOSE_WAIT。

      首先增加了连接池的参数 setValidateAfterInactivity(如下),发现不起作用。

    PoolingHttpClientConnectionManager connectionManager = new
                        PoolingHttpClientConnectionManager(socketFactoryRegistry);
                connectionManager.setValidateAfterInactivity(200);

      然后在初始化HttpClient时增加了参数 evictIdleConnections ,发现生效。

                CloseableHttpClient httpClient = HttpClients.custom()
                        .setSSLSocketFactory(csf)
                        .setConnectionManager(connectionManager)
                        .evictIdleConnections(2, TimeUnit.SECONDS)
                        .build();

      通过分析源码发现,RestTemplate在不做额外配置的情况下,会默认开启KeepAlive,而服务端不进行额外配置的时候,不会返回额外的内容,此时客户端进行了相关的判断之后,如果响应头没有Keep-Alive会返回-1,即认为默认不释放,后续服务端进行相应的连接的断开时,客户端认为可重用,就不进行清理,导致一致处于CLOSE_WAIT状态,而由于使用了大量的RestTemplate,导致大量的CLOSE_WAIT出现。

    连接池的配置不起作用是因为底层调用的是连接池的release方法,而release方法内部会进行相应的判断,如果发现是可重用的链接,就不会释放。

    CloseableHttpClient的配置生效是因为底层是查看是否过期,如果过期,则调用关闭方法。

  • 相关阅读:
    面试题4:替换空格之发散思维
    一个简单的欢迎webpart
    MOSS2010 选项卡
    在Ribbon中添加自定义按钮
    老中医
    [SharePoint 2010 的那些事儿 – Secure Store Service]SharePoint 2010中的单点登录
    使用SharePoint Designer2010 向SharePoint2010的Ribbon中添加自定义操作
    耐心看完,越到后面越精彩
    高端人才必看,生意人必读
    moss 2010 开发人员面板的使用
  • 原文地址:https://www.cnblogs.com/meiwangqing/p/10712829.html
Copyright © 2020-2023  润新知