各スレッドが対応する URL を 1 秒ごとにポーリングする 1000 個の専用 Java スレッドがあります。
public class Poller {
public static Node poll(Node node) {
GetMethod method = null;
try {
HttpClient client = new HttpClient(new SimpleHttpConnectionManager(true));
......
} catch (IOException ex) {
ex.printStackTrace();
} finally {
method.releaseConnection();
}
}
}
スレッドは 1 秒ごとに実行されます。
for (int i=0; i <1000; i++) {
MyThread thread = threads.get(i) // threads is a static field
if(thread.isAlive()) {
// If the previous thread is still running, let it run.
} else {
thread.start();
}
}
問題は、ジョブを 1 秒ごとに実行すると、次のようなランダムな例外が発生することです。
java.net.BindException: Address already in use
INFO httpclient.HttpMethodDirector: I/O exception (java.net.BindException) caught when processing request: Address already in use
INFO httpclient.HttpMethodDirector: Retrying request
しかし、2 秒以上ごとにジョブを実行すると、すべて正常に実行されます。
shutDown() を使用して SimpleHttpConnectionManager() のインスタンスをシャットダウンしようとしましたが、効果はありませんでした。
netstat を実行すると、数千の TCP 接続が TIME_WAIT 状態にあることがわかります。これは、それらが閉じられており、クリアされていることを意味します。
したがって、接続数を制限するために、HttpClient の単一インスタンスを使用して、次のように使用してみました。
public class MyHttpClientFactory {
private static MyHttpClientFactory instance = new HttpClientFactory();
private MultiThreadedHttpConnectionManager connectionManager;
private HttpClient client;
private HttpClientFactory() {
init();
}
public static HttpClientFactory getInstance() {
return instance;
}
public void init() {
connectionManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams managerParams = new HttpConnectionManagerParams();
managerParams.setMaxTotalConnections(1000);
connectionManager.setParams(managerParams);
client = new HttpClient(connectionManager);
}
public HttpClient getHttpClient() {
if (client != null) {
return client;
} else {
init();
return client;
}
}
}
しかし、ちょうど 2 時間実行した後、「開いているファイルが多すぎます」というメッセージがスローされ始め、最終的には何もできなくなります。
ERROR java.net.SocketException: Too many open files
INFO httpclient.HttpMethodDirector: I/O exception (java.net.SocketException) caught when processing request: Too many open files
INFO httpclient.HttpMethodDirector: Retrying request
許可される接続数を増やして機能させることができるはずですが、悪を長引かせるだけです。上記のような状況で HttpClient を使用するベストプラクティスは何ですか?
ところで、私はまだ HttpClient3.1 を使用しています。