Meu servidor Web VPS em execução no CentOS 5.4 (kernel Linux 2.6.16.33-xenU) de forma irregular (como uma vez por mês durante algumas semanas) deixa de responder devido à ativação do oom-killer. O monitoramento do servidor mostra que ele não funciona. normalmente ficam sem memória, de vez em quando.
Eu li alguns blogs que apontam para esta página que discutem a configuração do kernel para gerenciar melhor a supercomprometimento usando as seguintes configurações do sysctl:
vm.overcommit_memory = 2
vm.overcommit_ratio = 80
Meu entendimento disso (que pode estar errado, mas não consigo encontrar uma definição canônica para esclarecer) é que isso impede que o kernel superaloque a memória além da troca + 80% da memória física.
No entanto, eu também li algumas outras fontes sugerindo que essas configurações não são uma boa idéia - embora os críticos dessa abordagem pareçam estar dizendo "não faça coisas para danificar seu sistema, em vez de tentar esse argumento", supondo que a causação é sempre conhecida.
Então, minha pergunta é: quais são os prós e os contras dessa abordagem , no contexto de um servidor Apache2 que hospeda cerca de 10 sites de baixo tráfego? No meu caso específico, o servidor da Web possui 512 MB de RAM, com 1024 MB de espaço de troca. Isso parece adequado para a grande maioria das vezes.
/proc/<PID>/oom_score_adj
para esse fim. Por exemplo, se você definir oom_score_adj como -1000 para sshd, o oom killer nunca terá como alvo o sshd quando quiser matar alguma coisa. Interromper completamente o assassino não é uma boa ideia, pois seus programas não serão capazes de prejudicar a memória e eles morrerão de qualquer maneira.A Seção 9.6 "Confirmação excessiva e OOM" no documento mencionado pelo @dunxd é particularmente gráfica sobre os perigos de permitir a confirmação excessiva. No entanto,
80
parecia interessante para mim, então realizei alguns testes.O que descobri é que isso
overcommit_ratio
afeta a RAM total disponível para TODOS os processos. Os processos raiz não parecem ser tratados de maneira diferente dos processos normais do usuário.Definir a proporção como
100
ou menos deve fornecer a semântica clássica da qual os valores de retornomalloc/sbrk
são confiáveis. Definir taxas mais baixas do que100
pode ser uma maneira de reservar mais RAM para atividades não relacionadas ao processo, como cache e assim por diante.Então, no meu computador com 24 GiB de RAM, com swap desativado, 9 GiB em uso,
top
mostrandoAqui estão algumas
overcommit_ratio
configurações e quanta RAM meu programa consumidor de memória ram poderia pegar (tocando em cada página) - em cada caso, o programa saiu de forma limpa uma vez quemalloc
falhou.A execução de vários de uma só vez, mesmo com alguns como usuário root, não alterou a quantidade total que consumiram juntos. É interessante que não foi possível consumir os últimos 3 ou mais GiB; o
free
não caiu muito abaixo do que é mostrado aqui:Os experimentos foram confusos - qualquer coisa que use malloc no momento em que toda a RAM está em uso tende a falhar, já que muitos programadores são péssimos em verificar falhas de malloc em C, algumas bibliotecas populares de coleções o ignoram completamente e C ++ e várias outras linguagens são até pior.
A maioria das implementações iniciais da RAM imaginária que vi foram para lidar com um caso muito específico, em que um único processo grande - digamos 51% + de memória disponível - era necessário
fork()
paraexec()
um programa de suporte, geralmente um muito, muito menor. Sistemas operacionais com semântica de copiar na gravação permitiriamfork()
, mas com a condição de que, se o processo bifurcado realmente tentasse modificar muitas páginas de memória (cada uma das quais teria que ser instanciada como uma nova página independente do enorme processo inicial) acabaria sendo morto. O processo pai só estava em perigo se alocasse mais memória e poderia se esgotar, em alguns casos, apenas esperando um pouco para que outro processo morresse e continuando. O processo filho geralmente apenas se substitui por um programa (geralmente menor) viaexec()
e foi então livre da condição.O conceito de supercomprometimento do Linux é uma abordagem extrema para permitir que ambos
fork()
ocorram, bem como permitir que processos únicos sejam generalizados em massa. Mortes OOM-causou-assassinas acontecer de forma assíncrona, até programas que fazer alocação de memória alça de forma responsável. Pessoalmente, odeio o comprometimento excessivo em todo o sistema em geral e o assassino em particular - ele promove uma abordagem demolidora para o gerenciamento de memória que infecta bibliotecas e, por meio deles, todos os aplicativos que os usam.Eu sugeriria definir a proporção para 100 e ter uma partição de troca que geralmente acabaria sendo usada por processos enormes - que geralmente usam apenas uma pequena fração da parte de si que é armazenada na troca e, portanto, proteja a grande maioria dos processos das falhas de funcionalidade do OOM killer. Isso deve manter seu servidor da web protegido contra morte aleatória e, se ele foi escrito para lidar com
malloc
responsabilidade, pode até se matar (mas não aposte nesse último).Isso significa que estou usando isso no
/etc/sysctl.d/10-no-overcommit.conf
fonte