«Слишком много open files »в приложении grails - как мне правильно закрыть открытые файлы и потоки?

Я разрабатываю довольно сложное веб-приложение, которое вызывает несколько процессов, выполняемых извне, фоновый процесс grails и читает / записывает из / в несколько файлов - все в одном контроллере. Все было хорошо, пока я не проверил его со многими запросами в непосредственной близости от времени. Когда я это делаю, я получаю следующее сообщение об ошибке java в моем лог-файле tomcat catalina:

WARNING: Exception executing accept
java.net.SocketException: Too many open files
    at java.net.PlainSocketImpl.socketAccept(Native Method)
    at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
    at java.net.ServerSocket.implAccept(ServerSocket.java:462)
    at java.net.ServerSocket.accept(ServerSocket.java:430)
    at org.apache.jk.common.ChannelSocket.accept(ChannelSocket.java:312)
    at org.apache.jk.common.ChannelSocket.acceptConnections(ChannelSocket.java:666)
    at org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(ChannelSocket.java:877)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
    at java.lang.Thread.run(Thread.java:662)

Сначала, после некоторого удачного поиска в Google и чтения, я подозревал, что это может быть «системная проблема», т. Е. Что я должен увеличить предел для открытых файлов для пользователя, который запускает tomcat, но это не так.

Затем я начал читать много советов по Java, а не по Grails и Groovy, потому что, если вы загуглите эту проблему с Grails, вы не найдете так много. Теперь я подозреваю, что моя проблема вызвана «слишком большим количеством открытых потоков» (или чем-то в этом роде) вместо слишком большого количества действительно открытых файлов (поскольку количество открытых файлов действительно не ТАКОЕ).

У меня есть много операций следующих четырех типов в одном закрытии:

1) Открытие файлов и запись в них:

def someFile = new File("/some/file.txt")
someFile << "Some content\n"

2) Выполнение команд:

def cmd = "bash some-cmd".execute()
cmd.waitFor()

3) Чтение содержимого из файлов:

def fileContent = new File("/some/file.txt").text

4) Чтение содержимого из файлов в сети:

def URL url = new URL("http://www.some.link");
def URLConnection uc = url.openConnection()
def BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()))
...
br.close()

Как видите, единственное, что я явно закрываю, - это BufferedReader с InputStream, я считаю, что br.close () закрывает их оба.

Должен ли я закрыть какие-либо другие открытые соединения, или лучше: я могу это сделать? Какая будет команда для этого? Или вы думаете, что моя проблема действительно не вызвана «забытым открытым потоком»?

Мой вопрос в основном связан с ответами на Почему я получаю ошибки «Слишком много открытых файлов»? и IOException: слишком много открытых файлов .

Я использую grails 1.1.1 (я ЗНАЮ, что он устарел, но у меня были серьезные проблемы с переносом моего приложения на текущую версию, и я отказался от него после многих часов работы), groovy 1.8.0, tomcat 6.0. 28, apache 2.2.16 в ubuntu 10.10.

Решение моей проблемы «Слишком много открытых файлов» очень связано с ответом Стивена С. Похоже, что первой причиной моей ошибки действительно был незакрытый поток BufferedReader. Я в основном перенес его предложение java-кода прямо в grails:

def URL url = new URL("http://www.some.link");
def URLConnection uc = url.openConnection()
def BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()))
try{
    ...
}finally{
    br.close()
}

-> Это определенно решило проблему «Слишком много открытых файлов», и теперь я даже могу увидеть, что было настоящим источником проблемы.

5
задан Community 23 May 2017 в 10:31
поделиться