我刚开始写一个简单的网络爬虫来获取我们进入系统的链接信息。我使用httpclient 4.x.我有大约100个线程运行获取链接并对它们进行头部请求,它在最初的几个小时内运行很好,然后减慢到尖锐的抓取。我不确定是否正确设置了连接管理器。关于httpclient性能的困惑
这里是我必须创建一个httpclient对象的代码。任何人都可以看到任何会引发此代码块报警的事情?当我停止服务器并重新启动时,所有事情都像新的一样好。在运行缓慢的阶段,每个进程稳定的500K内存仍然看起来不错,所以它看起来不像我在泄漏内存。
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
ConnManagerParams.setMaxTotalConnections(httpParams, 200);
HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
// set request params
httpParams.setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
httpParams.setParameter("http.useragent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", PlainSocketFactory.getSocketFactory(), 443));
final ClientConnectionManager cm = new ThreadSafeClientConnManager(httpParams,schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm, httpParams);
httpClient.getParams().setParameter("http.conn-manager.timeout", 10000L);
httpClient.getParams().setParameter("http.protocol.wait-for-continue", 10000L);
我还使用一个线程的代码进行清理过期的连接,如文档
提到final Runnable cleanUp = new Runnable() {
public void run() {
cm.closeExpiredConnections();
// Optionally, close connections
// that have been idle longer than 30 sec
cm.closeIdleConnections(30, TimeUnit.SECONDS);
}
};
更新: 我跑的视觉VM了一个小时左右,这里的记忆在远程进程曲线图中,存储器是现在使用最多
http://img64.imageshack.us/f/screenshot20100714at204.png/
我知道你说内存看起来很稳定,但是你启用了GC日志记录吗?你在GC上花费了多少时间? – bwawok 2010-07-14 16:05:43
我其实并不是很新,对于java来说很新,所以不知道我可能会在哪里设置 – James 2010-07-14 16:08:13
你是网络I/O绑定的,100个线程可能使你的网络连接饱和。然后你就是磁盘I/O绑定。 – 2010-07-14 16:40:50