我有一个应用程序,它使用HttpClient (4.1.3 or 4.2-beta)
. 它在 Windows 7 64 位上运行。处理器 - 酷睿 i7 2600K。网络带宽 - 54 Mb/s。
此时它使用这样的参数:
DefaultHttpClient
和PoolingClientConnectionManager
;- 它也有
IdleConnectionMonitorThread
来自
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html
; - 最大总连接数 = 80;
- 每条路由的默认最大连接数 = 5;
- 对于线程管理,它使用
ForkJoinPool
并行
级别 = 5(我是否正确理解它是多个工作
线程?)
在这种情况下,我的网络使用率(在 Windows 任务管理器中)没有超过 2.5%。下载 4500 个页面需要 70 分钟。在 HttpClient 日志中,我有这样的事情:
调试 ForkJoinPool-2-worker-1 [org.apache.http.impl.conn.PoolingClientConnectionManager]:连接释放:[id:209][路由:{}->http://stackoverflow.com][总保持活动: 6;分配的路线:5 条中的 1 条;总分配:80 个中的 10 个]
分配的连接总数不会超过 10-12,尽管我已将其设置为 80 个连接。如果我尝试将并行度提高到 20 或 80,网络使用率保持不变,但会产生很多连接超时。
我已经阅读了 hc.apache.org 上的教程(HttpClient Performance Optimization Guide和HttpClient Threading Guide),但它们没有帮助。
任务的代码如下所示:
public class ContentDownloader extends RecursiveAction {
private final HttpClient httpClient;
private final HttpContext context;
private List<Entry> entries;
public ContentDownloader(HttpClient httpClient, List<Entry> entries){
this.httpClient = httpClient;
context = new BasicHttpContext();
this.entries = entries;
}
private void computeDirectly(Entry entry){
final HttpGet get = new HttpGet(entry.getLink());
try {
HttpResponse response = httpClient.execute(get, context);
int statusCode = response.getStatusLine().getStatusCode();
if ( (statusCode >= 400) && (statusCode <= 600) ) {
logger.error("Couldn't get content from " + get.getURI().toString() + "\n" + response.toString());
} else {
HttpEntity entity = response.getEntity();
if (entity != null) {
String htmlContent = EntityUtils.toString(entity).trim();
entry.setHtml(htmlContent);
EntityUtils.consumeQuietly(entity);
}
}
} catch (Exception e) {
} finally {
get.releaseConnection();
}
}
@Override
protected void compute() {
if (entries.size() <= 1){
computeDirectly(entries.get(0));
return;
}
int split = entries.size() / 2;
invokeAll(new ContentDownloader(httpClient, entries.subList(0, split)),
new ContentDownloader(httpClient, entries.subList(split, entries.size())));
}
}
问题是 - 使用多线程的最佳实践是什么,HttpClient
可能有一些设置规则吗?如何使用全部 80 个连接并提高网络使用率?ConnectionManager
HttpClient
如有必要,我将提供更多代码。