情景
后端部署了新的代码,在几分钟后似乎所有的爬取相关的服务均不可用。一服务频繁报错提示:「连接超时: 当前过于拥挤」。
获取连接池状态
首先立即打开日志查看错误消息,显示:Timeout waiting for connection from pool ,字面意思是从连接池中等待超时。为了了解这个时候的连接池状态如何,在查找资料后,使用以下的代码在出现异常的同时打印当前连接池状态。
for(HttpRoute route : customConnectionPool.getRoutes()){
logger.info("{} :: {}", route.getTargetHost().getHostName() ,customConnectionPool.getStats(route));
}
PoolStats
连接池每个路由(可以认为一个Host:IP为一个路由/Route)的状态由PoolStats这个类表示。这个类有四个字段用于表示该路由对应状态下的连接,每个字段对应一种状态。
leased
“租用”,即表示当前正在被使用的连接。如果这个状态长期保持一个较高的数量,尤其是只增不减,应该要考虑到是连接用完后没有释放的问题了(后话)。
pending
“等待”,表示有请求在等待连接池可用连接,等待超时时间可以在RequestConfig.custom()
中使用setConnectionRequestTimeout
设置(单位为ms),超时后即抛出题示异常。
available
“可用”,表示空闲的持久连接。根据源码文档,该路由的当前总存在连接数=leased+available。
max
表示路由最大可以创建的连接数,这个数量取决于PoolingHttpClientConnectionManager
的setDefaultMaxPerRoute
值,或者是由HttpClients.custom()
的setMaxConnPerRoute
决定。
连接池的总大小(连接数量)的一个坑
最初代码是这样写的:
customConnectionPool = new PoolingHttpClientConnectionManager();
customConnectionPool.setDefaultMaxPerRoute(1500);