业务中有一个场景需要在server端发起Http请求获取相关数据,为了提升性能,在代码中使用了HttpClient的连接池,上线一段时间后发现HttpClient的活跃连接数一直在增长,HttpClient连接池的总数是有限制的,当活跃的连接数把连接池中的连接全局消耗完之后,就无法在发起新的Http请求,导致出现线上问题。
这个问题的原因很明显是出现的资源泄漏,一切类似池的原理,包括连接池、线程池等,很重要的一个原则就是有借有还。在开始的时候初始化一定数量的资源放入池中,使用方需要的时候不是初始化一个资源,而是从池中租借一个资源,在使用完之后不销毁资源,而是归还到池中。这样可以省去每次初始化和销毁资源的操作,从而提高性能。
回到当前的这个问题,排查代码发现在发送Http请求的时候,偶尔会有异常的情况,这个时候没有对HttpResponse进行处理,导致这些连接一直处于被占用状态,没有归还到连接池中。
开发人员在写代码时还是要详细阅读下使用组件的说明文档,这个问题在HttpClient时使用说明已经很明确的说明了,详见http://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html
The underlying HTTP connection is still held by the response object to allow the response content to be streamed directly from the network socket. In order to ensure correct deallocation of system resources the user MUST call CloseableHttpResponse#close() from a finally clause. Please note that if response content is not fully consumed the underlying connection cannot be
safely re-used and will be shut down and discarded by the connection manager.