Meu aplicativo que é baseado em dois processos Java que trocam dados em uma conexão http fica sem arquivos e produz esta mensagem de erro:
Aug 14 11:27:40 server sender[8301]: java.io.IOException: Too many open files
Aug 14 11:27:40 server sender[8301]: at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
Aug 14 11:27:40 server sender[8301]: at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
Aug 14 11:27:40 server sender[8301]: at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
Aug 14 11:27:40 server sender[8301]: at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:455)
Aug 14 11:27:40 server sender[8301]: at java.lang.Thread.run(Thread.java:748)
Ambos os processos estão sob controle do SystemD. Eu verifiquei os processos usando cat /proc/5882/limits
, os limites são definidos assim:
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 63434 63434 processes
Max open files 4096 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 63434 63434 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Quando executo lsof | grep pid | wc -l
, tenho menos de 2000 entradas (executo lsof dessa maneira por causa das informações recuperadas do comando Discrepancy com lsof ao tentar obter a contagem de arquivos abertos por processo )
Não tenho a menor ideia do que poderia verificar ou aumentar ainda mais.
A melhor maneira de saber quantos descritores de arquivos abertos seu processo possui é usar:
(Assumindo o PID 8301, como no seu log.)
A execução
lsof
percorrerá toda a/proc
árvore e tentará resolver os nomes de todos os arquivos (estes são pseudo-links simbólicos e precisam de uma chamada para readlink para resolução), portanto, a execuçãolsof
levará muito tempo (dependendo de quão ocupada sua máquina estiver), então, quando você olhar para o resultado, é possível que tudo já tenha mudado. O usols /proc/${pid}/fd/
será rápido (apenas uma chamada readdir), muito mais provável de capturar algo próximo à situação atual.Com relação à solução do problema, você pode considerar aumentar o número de descritores de arquivo permitidos ao seu serviço, o que pode ser feito definindo a
LimitNOFILE=
diretiva em seu arquivo de unidade systemd.