У меня есть 1000 выделенных потоков Java, где каждый поток опрашивает соответствующий URL каждую секунду.
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();
}
}
}
Потоки запускаются каждую секунду:
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();
}
}
Проблема в том, что если я запускаю задание каждую секунду, я получаю случайные исключения, подобные этим:
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 секунды или более, все работает нормально.
Я даже пытался закрыть экземпляр SimpleHttpConnectionManager () с помощью shutDown () безрезультатно.
Если я выполняю 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.