我有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秒钟或更长时间运行一次,那么一切都运行良好。
我甚至尝试使用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。答案 0 :(得分:3)
有关更多性能提示,请参阅http://hc.apache.org/httpclient-3.x/performance.html。
更新:哎呀,我没看过下面的代码示例。如果您正在执行releaseConnection()并使用MultiThreadedHttpConnectionManager,请考虑您对每个进程的打开文件的操作系统限制是否设置得足够高。我们也遇到了这个问题,需要稍微扩展一下限制。
答案 1 :(得分:2)
第一次错误没有错。你刚刚耗尽了可用的经验端口。每个TCP连接可以保持TIME_WAIT状态2分钟。你生成2000 /秒。不久之后,套接字找不到任何未使用的本地端口,您将收到该错误。 TIME_WAIT正是为此目的而设计的。没有它,您的系统可能会劫持先前的连接。
第二个错误表示您打开了太多套接字。在某些系统上,打开文件的限制为1K。也许你只是因为延迟套接字和其他打开的文件而达到了这个限制。在Linux上,您可以使用
更改此限制 ulimit -n 2048
但这受到系统范围最大值的限制。
答案 2 :(得分:0)
以sudo或root编辑/etc/security/limits.conf文件。在“#File of File”上方的文件末尾输入以下值: * soft nofile 65535 * hard nofile 65535 这会将打开的文件数设置为无限制。