を使用して、62 のターゲット ホストから 4500 を超える html ページをダウンロードするアプリケーションがありますHttpClient (4.1.3 or 4.2-beta)
。Windows 7 64 ビットで動作します。プロセッサ - コア i7 2600K。ネットワーク帯域幅 - 54 Mb/秒。
現時点では、次のようなパラメーターを使用しています。
DefaultHttpClient
そしてPoolingClientConnectionManager
;- また、から持ってい
IdleConnectionMonitorThread
ます
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html
。 - 最大合計接続数 = 80;
- ルートごとのデフォルトの最大接続数 = 5;
- スレッド管理には
ForkJoinPool
、並列度=5で使用しています(作業 スレッド
数だと正しく理解できていますか?)
この場合、(Windows タスク マネージャーでの) ネットワーク使用率は 2.5% を超えません。4500 ページをダウンロードするには 70 分かかります。そして、HttpClient ログには次のようなものがあります。
DEBUG ForkJoinPool-2-worker-1 [org.apache.http.impl.conn.PoolingClientConnectionManager]: 接続が解放されました: [id: 209][ルート: {}->http://stackoverflow.com][合計キープアライブ: 6; 割り当てられたルート: 1/5; 割り当てられた合計: 10/80]
割り当てられた接続の合計は、最大 80 接続に設定したにもかかわらず、10-12 を超えません。並列処理レベルを 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
問題は、マルチ スレッドを使用するためConnectionManager
のベスト プラクティスは何HttpClient
ですか。80 接続すべてを使用してネットワーク使用率を上げるにはどうすればよいですか?
必要に応じて、さらにコードを提供します。