Подтвердить что ты не робот

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)
4b9b3361

Ответ 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.

Ответ 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;
}