Java.net.SocketException: слишком много открытых файлов
У меня есть приложение java, которое работает отлично (на Ubuntu 10.04) в течение нескольких часов, пока оно не попадет в "java.net.SocketException: Слишком много открытых файлов". Код для Sender.java можно найти здесь
Это потому, что я создаю новый экземпляр HttpPut
и HttpPost
для каждого потока? Я использую apache-commons HTTPClient 4.
Здесь журнал исключений:
java.net.SocketException: Too many open files
at java.net.Socket.createImpl(Socket.java:414)
at java.net.Socket.connect(Socket.java:544)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:123)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:133)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at com.marketplace.io.Sender.doBasicHttpPost(Sender.java:434)
at com.marketplace.io.Sender.appVisualExists(Sender.java:223)
at com.marketplace.io.Sender.addVisualToCollection(Sender.java:350)
at com.marketplace.service.ImageThread.run(ImageThread.java:136)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
Ответы
Ответ 1
В строке 438 вы получите ответ как поток и преобразуете его в массив байтов. InputStream, возвращаемый entity.getContent(), не закрывается. Это может способствовать решению этой проблемы. Кроме того, HttpEntity.consumeContent() устарел по другим причинам.
Ответ 2
"java.net.SocketException: слишком много файлов открываются" можно увидеть любое приложение Java Server, например. Tomcat, Weblogic, WebSphere и т.д., Когда клиент часто подключается и отключается.
Обратите внимание, что соединения сокетов обрабатываются как файлы, и они используют дескриптор файла, который является ограниченным ресурсом.
Различные операционные системы имеют разные ограничения на количество обрабатываемых файлов.
Короче говоря, эта ошибка исходит из-за того, что клиенты часто подключаются и отключаются. Если вы хотите обработать ее на своей стороне, у вас есть два варианта:
1) Увеличить количество открытых файлов или дескрипторов файлов для каждого процесса.
В операционной системе на базе UNIX, например. Ubuntu или Solaris, вы можете использовать команду ulimit -a, чтобы узнать, сколько разрешено открывать файлы для каждого процесса.
$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 2048
virtual memory (kbytes, -v) unlimited
Вы можете видеть, что открывать файлы (-n) 256, что означает, что разрешено всего 256 открытых файлов для каждого процесса. Если ваша Java-программа, помните Tomcat, weblogic или любой другой сервер приложений, являются Java-программами, и они запускаются на JVM, превышают этот предел, он будет генерировать java.net.SocketException: слишком много файлов открывают ошибку.
Вы можете изменить этот предел, используя ulimit -n на большее число, например. 4096, но сделайте это с рекомендацией системного администратора UNIX, и если у вас есть отдельная команда поддержки UNIX, чем лучше переходить на них.
2) Уменьшите таймаут для состояния TIME_WAIT в вашей операционной системе
В системах на базе UNIX вы можете увидеть текущую конфигурацию в файле /proc/sys/net/ipv4/tcp_fin_timeout.
В системе на базе Windows вы можете увидеть эту информацию в реестре Windows. Вы можете изменить тайм-аут TCPTIME_WAIT в Windows, выполнив следующие шаги:
1) Open Windows Registry Editor, by typing regedit in run command window
2) Find the key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Parameters
3) Add a new key value pair TcpTimedWaitDelay asa decimal and set the desired timeout in seconds (60-240)
4) Restart your windows machine.
Ответ 3
Вы также можете проверить максимальный максимальный открытый линус Linux. Эта связанная ссылка предназначена для индивидуального Java-продукта, но она прекрасно объясняет шаги, необходимые для устранения проблемы.
Ответ 4
(ПОСТАНОВИЛИ)
Недавно у меня была такая же ошибка, потому что сервер данных var/log на сервере данных полностью.
#df -h
S.ficheros Size Used Avail Use% Montado en
/dev/cciss/c0d0p3 126G 126G 0G 100% /var
#echo "">/var/log/postgresql/postgresql.log
Теперь ошибка исчезла.
important: посмотрите, что запишите в postgresql.log, просмотрите файл postgresql.conf
До свидания
@_jpgo
Ответ 5
Я решаю проблему, закрывая соединение в блоке finally.
public static String postMethod(String jsonStr,String sendUrl){
String resultJson = "";
HttpClient httpClient = new HttpClient();
PostMethod post = new PostMethod(sendUrl);
post.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");
NameValuePair[] param = { new NameValuePair("message",jsonStr)} ;
post.setRequestBody(param);
try {
httpClient.executeMethod(post);
resultJson = post.getResponseBodyAsString();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
post.releaseConnection();
((SimpleHttpConnectionManager)httpClient.getHttpConnectionManager()).shutdown();
}
return resultJson;
}