Está definindo ulimit -v suficiente para evitar vazamento de memória

2

Temos um processo que nas últimas semanas teve um vazamento de memória que resultou em consumir toda a memória em nossa caixa do RHEL 7

Agora desejamos estabelecer limites em torno disso, de modo que ele nunca demore mais do que uma certa quantia

Estamos usando a configuração ulimit -v para definir esse valor (pois a configuração -m não funciona)

Portanto, estou pensando se isso é suficiente ou também precisamos de uma maneira de limitar a memória física? Em caso afirmativo, qual é a melhor maneira de fazer isso?

Se a memória virtual sempre cresce com a memória phyiscal, então talvez -v por si só seja suficiente

    
por DJ180 20.04.2018 / 18:25

1 resposta

2

Alguma descrição sobre como ulimit funciona:

ulimit lidou com setrlimit e getrlimit chamadas do sistema. É fácil garantir por strace -ing do processo bash ( ulimit é componente do bash ). Eu defino 1024kb de max memory size :

$ ulimit -m 1024

Em outro console:

$ strace -p <my_bash_pid>
. . .
getrlimit(RLIMIT_RSS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
setrlimit(RLIMIT_RSS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
. . . 

setrlimit man page escreve em seguida sobre RLIMIT_RSS :

RLIMIT_RSS Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.

madvice syscall é apenas um conselho para o kernel e o kernel pode ignorar este conselho. Mesmo bash man page sobre ulimit , escreva:

-m The maximum resident set size (many systems do not honor this limit)

Essa é a razão pela qual -m não funciona.

Sobre a opção -v :

Eu defino 1024 kb de memória virtual:

$ ulimit -v 1024

Em outro console:

$ strace -p <my_bash_pid>
. . .
getrlimit(RLIMIT_AS, {rlim_cur=RLIM64_INFINITY, rlim_max=RLIM64_INFINITY}) = 0
setrlimit(RLIMIT_AS, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
. . .

setrlimit man page escreve em seguida sobre RLIMIT_AS :

RLIMIT_AS The maximum size of the process's virtual memory (address space) in bytes. This limit affects calls to brk(2), mmap(2) and mremap(2), which fail with the error ENOMEM upon exceeding this limit. Also automatic stack expansion will fail (and generate a SIGSEGV that kills the process if no alternate stack has been made available via sigaltstack(2)). Since the value is a long, on machines with a 32-bit long either this limit is at most 2 GiB, or this resource is unlimited.

O programa consiste em 3 segmentos (dados, código, pilha) que compõem o espaço de memória do programa virtual.

  • O segmento do código é const e contém instruções do programa.

  • O segmento de dados é controlado da seguinte forma:

    brk syscall ajusta o tamanho do segmento de dados (parte da memória virtual ) do programa.

    mmap syscall mapeia o arquivo ou dispositivo para a memória virtual do processo.

    Muitos programas alocam memória (direta ou indireta) chamando a função padrão da Biblioteca C ( malloc ) que aloca memória de heap (parte do segmento de dados). malloc ajusta o tamanho do segmento de dados chamando brk syscall.

  • O Stack armazena variáveis de funções (a variável recebe memória durante a alocação da pilha).

Então, é por isso que a opção -v funciona para você.

Se -v for suficiente para sua tarefa, não há motivos para fazer outra coisa e é suficiente.

Se você deseja controlar grandes quantidades de recursos de memória específicos para processos (pressão de memória, uso de swap, limite de RSS, OOM e assim por diante), sugiro que você use pacotes de memória .

Se seu aplicativo for um serviço , sugiro que você use Recursos do systemd slice , como o mais conveniente para controlar e limitar recursos de serviço ou grupo de serviços (também é fácil configurar em vez de configurar cgroups diretamente) que é gerenciado por systemd .

    
por 21.04.2018 / 19:04