Too many open files
Является распространенным исключением Java, обычно вызванным конфигурацией системы или программой, открывающей слишком много файлов. Эта проблема часто связана сulimit
использование связанных. оulimit
В использовании есть много подводных камней, в этой статье мы разберемся с ними.
Исключение слишком много открытых файлов
Ниже приведен стек исключений Java, когда система превышает максимальное количество открытых файлов:
Exception in thread "main" java.io.IOException: Too many open files
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createTempFile(File.java:2024)
at java.io.File.createTempFile(File.java:2070)
at com.imshuai.wiki.ulimit.App.main(App.java:16)
Если это не программная проблема (программная проблема, надо посмотреть почему открывается много файлов, например через lsof), то вообще решается настройкой лимита количества открытых файлов через ulimit, но у самого ulimit тоже много ямы, так что подведем итоги.
что такое улимит
Обратитесь непосредственно к справочному документу ulimit (примечание: не man ulimit, а help ulimit, ulimit — это встроенная команда, первая предоставляет справку по ulimit на языке C):
Modify shell resource limits.
Provides control over the resources available to the shell and processes it creates, on systems that allow such control.
Как можно видеть,ulimit обеспечивает управление ресурсами, доступными для оболочки (или процессов, созданных оболочкой).. Помимо количества открытых файлов, управляемыми ресурсами являются:
Максимальный размер файла записи, максимальный размер стека, размер файла дампа ядра, ограничение времени ЦП, максимальный размер виртуальной памяти и т. д., help ulimit перечислит ресурсы, ограниченные каждым параметром. или просмотретьulimit -a
Также можно увидеть, что:
maoshuai@ms:~/ulimit_test$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) 100
pending signals (-i) 15520
max locked memory (kbytes, -l) 16384
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 15520
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
понять ulimit
Прежде чем использовать ulimit, есть несколько непонятных моментов:
Измерение управления ulimit
Чтобы понять ulimit, первый вопрос заключается в том, какова размерность предела. Например, если для параметра nofile задано значение 1024, это означаетТекущий пользовательВсего можно открыть только 1024 файла, илипроцесс сеанса с одной оболочкойМожет открывать только 1024 файла? ** На самом деле, help ulimit дал понять: процесс, но мы можем проверить это с помощью следующего метода:
Давайте откроем 800 файлов через java-программу:
class Ulimit{
public static void main( String[] args ) throws IOException, InterruptedException
{
List<FileInputStream> fileList = new ArrayList<FileInputStream>();
for(int i=0;i<800;i++) {
File temp = File.createTempFile("ulimit-test", ".txt");
fileList.add(new FileInputStream(temp));
System.out.println("file_seq=" + i + " " + temp.getAbsolutePath());
}
// keep it running, so we can inspect it.
Thread.sleep(Integer.MAX_VALUE);
}
}
Мы устанавливаем nofile на 1024
ulimit -n 1024
Затем мы запускаем два экземпляра процесса:
nohup java Ulimit >a.log &
nohup java Ulimit >b.log &
При проверке журналов a.log и b.log было создано 800 файлов, и ни об одном исключении не сообщалось.
Если вы установите ulimit на 700, повторите проверку и обнаружите, что программа Java сообщает, когда создает 688 файлов.Too many open files
Исключение (причина не 700 в том, что сама java тоже открывает некоторые файлы),
file_seq=688 /tmp/ulimit-test7270662509459661456.txt
Exception in thread "main" java.io.IOException: Too many open files
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createTempFile(File.java:2024)
at java.io.File.createTempFile(File.java:2070)
at Ulimit.main(Ulimit.java:12)
Хотя u в ulimit означает пользователя, оказывается,Измерение, контролируемое ulimit, — это сеанс оболочки или процесс, созданный оболочкой (по крайней мере, для nofile). То есть количество файлов, открытых текущим пользователем, может намного превышать значение nofile.
Итак, поlsof | wc -l
Неверно проверять количество открытых файлов в системе, чтобы определить, не превышено ли количество открытых файлов. Кроме того,lsof | wc -l
Да и не отражает количество открытых системой файлов! (последующая еженедельная добавка)
Различие между мягким и твердым
Вторым важным аспектом понимания ulimit является различие между soft и hard.Ограничения Ulimit на ресурсы делятся на две категории: soft и hard, то есть один и тот же ресурс (например, nofile) имеет два значения soft и hard.
По команде ulimit различает soft и hard с помощью -S и -H. Если -S или -H не указаны, это относится к мягкому при отображении значения и относится к при его установкеУстановите как мягкие, так и жесткие значения.
Но в чем разница между мягким и твердым? Следующее объяснение является более точным (из man 2 getrlimit )
The soft limit is the value that the kernel enforces for the corresponding resource. The hard limit acts as a ceiling for the soft limit: непривилегированный процесс может установить только свое мягкое ограничение на значение в диапазоне от 0 до жесткого ограничения и** (необратимо) **понизить свое жесткое ограничение. возможности) может вносить произвольные изменения в любое предельное значение.
Обобщите разницу между мягким и твердым:
- Всякий раз, когда soft всегда меньше или равен hard
- Независимо от того, превышает ли он значение soft или hard, операция будет отклонена. В сочетании с первым пунктом это предложение эквивалентно следующему: При превышении мягкого лимита операция будет отклонена.
- Процесс может модифицировать soft или hard текущего процесса. Но модификация должна соответствовать правилам:
- После модификации soft не может превышать hard. То есть, когда soft увеличивается, он не может превышать hard; когда hard уменьшается до значения, меньшего, чем текущий soft, соответственно soft тоже уменьшается.
- Как некорневые, так и корневые процессы могут увеличивать или уменьшать soft произвольно в диапазоне [0-hard].
- Процесс без полномочий root может сильно уменьшаться, но не может сильно увеличиваться. То есть nofile изначально был 1000, а его модифицировали на 900. Модифицировать на 1000 нельзя. (Это односторонняя, безвозвратная операция)
- Корневой процесс может произвольно изменять жесткое значение.
Нет никакой разницы в управлении между soft и hard, что ограничит использование ресурсов, но soft можетМодифицируется самим процессом перед использованием.
Модификация и действие ulimit
Знать ulimit — это хорошо, но, что более важно, как его модифицировать, что является обычной задачей на работе.
Что касается эффекта ulimit, вы можете понять несколько моментов:
- Значение ulimit всегда наследует настройку родительского процесса.
- Команда ulimit изменяет настройки текущего процесса оболочки. Это также показывает, что,Чтобы гарантировать, что в следующий раз это вступит в силу, измененное место должно быть постоянным.(По крайней мере эквивалентно целевому процессу), например .bashrc или сценарий запуска процесса)
- Из пункта 2 также можно сделать вывод, что модификация ulimit не влияет на запущенный процесс.
- Увеличьте жесткое значение, что может быть сделано только пользователем root
Ниже приведены два случая:
Случай 1: Для процесса без полномочий root требуется nofile 2048. После проверки текущий софт — 1024, а хард — 4096
Вы можете напрямую добавить ulimit -nS 2048 в сценарий запуска процесса.
Случай 2: Процесс без полномочий root требует nofile 10240. После проверки текущий софт — 1024, а хард — 4096
Очевидно, что пользователи без полномочий root не могут пробиться. Может быть изменено только пользователем root, общая модификация/etc/security/limits.conf
файл, способ модификации также описан в комментариях в конфигурационном файле, формат такой:
Запись содержит 4 столбца, которые представляют собой домен диапазона (то есть эффективный диапазон, который может быть именем пользователя, именем группы или * для всех пользователей без полномочий root); тип t: то есть мягкий, жесткий или - означает установить как soft, так и hard; элемент элемента, элемент управления ресурсами в ulimit, перечисление имени может ссылаться на комментарии в файле; последнее является значением. Например, установите для nofile всех пользователей без полномочий root значение 100000.
* hard nofile 10000
* soft nofile 10000
Просмотр ограничений запущенного процесса
После изменения ulimit вы можете просмотреть его непосредственно с помощью команды ulimit.Также есть более точный способ просмотра запущенных процессов(Например, чтобы узнать значение ulimit процесса, запущенного до изменения ulimit, требуется этот метод): Проверьте файл limit в каталоге процесса. Например, файл /proc/4660/limits записывает все значения лимитов процесса 4660:
maoshuai@ms:~/ulimit_test$ cat /proc/4660/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 15520 15520 processes
Max open files 2000 2000 files
Max locked memory 16777216 16777216 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 15520 15520 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
ulimit без параметров
Раньше был Сяобай, который использовал его напрямуюulimit
посмотреть, посмотреть распечататьunlimited
, открытый файл считается неограниченным. Очевидно, это неправильно,help ulimit
четко заявляет:
If no option is given, then -f is assumed.
Поэтому ulimit не добавляет параметры, что эквивалентноulimit -f -S
(Это эквивалентно -S без указания -S или -H), что на самом деле относится к максимальному размеру файла, который может быть записан.
разное
Как проверить количество открытых файлов в системе
Хотя команда losf используется для «вывода списка открытых файлов», ее можно использовать сlsof | wc -l
Подсчет открытых файлов очень неточен. Основная причина:
- В некоторых случаях строка может отображать поток вместо процесса.В многопоточных случаях это будет ошибочно принято за многократно открываемый файл.
- Дочерние процессы совместно используют обработчики файлов
Если вы используете
lsof
Статистика, вы должны использовать сложные условия фильтрации. Более простой и точный способ — просмотр каталога /proc. Чтобы система открыла файл, посмотрите непосредственно на /proc/sys/file-nr, где первое число — это количество открытых файлов (ссылка на описание file-nr:woohoo.kernel.org/doc/doc U-дверь…).要查看一个进程的打开文件数,直接查看目录/proc/$pid/fd里的文件数即可:
Java будет автоматически обновлена на жесткий NOFile мягкий предел
В процессе исследования,Я обнаружил, что программа Java, похоже, не зависит от мягкого значения nofile.. Глядя на файл лимитов процесса (/proc/$pid/limits), я обнаружил, что программное обеспечение nofile было обновлено до того же, что и жесткое. Обыскав всю сеть,Обнаружено, что при реализации JDK soft из nofile будет напрямую изменен на то же значение, что и hard., вы можете обратиться к:How and when and where jvm change the max open files value of Linux?
Java, запущенная в eclipse в Ubuntu, и java, запущенная из командной строки, имеют разные nofiles
Через pstree установлено, что java eclipse запускается через gnome-shell, а командная строка запускается через gnome-terminal. где gnome-terminal снова запускается через systemd --user, который, похоже, не читает значение /etc/security/limits.conf. Описание этой ямы есть возможность заполнить заново.
file-max контролирует общее количество файлов, которые может открыть ядро.
Помимо контроля ulimit,/proc/sys/fs/file-max
Этот файл определяет общее количество файлов, которые может открыть ядро системы. Поэтому, даже если для параметра nofile в ulimit задано значение ulimited, он все равно ограничен.
ulimit общие параметры
ulimit -a # 查看所有soft值
ulimit -Ha # 查看所有hard值
ulimit -Hn # 查看nofile的hard值
ulimit -Sn 1000 # 将nofile的soft值设置为1000
ulimit -n 1000 # 同时将nofiles的hard和soft值设置为1000
Ссылаться на
- Session failures with error "Too many open files"
- ulimit man page
lsof | wc -l
sums up a lot of duplicated entries- How and when and where jvm change the max open files value of Linux?
- Why file-nr and lsof count on open files differs?
«Еженедельник изучения Java и Linux» выходит каждую пятницу и одновременно обновляется по адресу:Github,Знай почти,Наггетс