Como resolver a utilização elevada de memória em Linux
Como descobrir o que está a consumir a memória num servidor Linux, e quais as definições de overcommit do kernel que o controlam.
Identificar o cenário «Out of Memory».
A pressão pode já ter passado quando for ver, por isso procure primeiro OOM kills no log do kernel: o kernel do Linux gere a memória do servidor terminando tarefas e processos segundo determinados critérios e libertando a memória ocupada pelo processo terminado.
Por cada processo terminado pelo kernel é gerada uma entrada no log, e os logs encontram-se normalmente em /var/log/.
Com o comando grep abaixo procura um erro de out of memory em todos os ficheiros de log em /var/log/.
grep -i -r 'out of memory' /var/log/
Mar 1 01:24:05 srv kernel: [3966348.114233] Out of memory: Kill process 48305 (php-cgi) score 21 or sacrifice child
Mar 1 01:24:08 srv kernel: [3966350.061954] Out of memory: Kill process 48318 (php-cgi) score 21 or sacrifice child
Utilização atual:
root@srv:~# free -m
total used free shared buff/cache available
Mem: 1981 720 319 138 940 916
Swap: 524 84 440
O histórico da utilização de memória do dia obtém-se com o comando «sar».
root@server [~]# sar -r
Linux (server.example.com) 03/05/2019 _x86_64_ (2 CPU)
12:00:01 AM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit
12:10:01 AM 1672764 1407160 45.69 100356 749140 1618364 44.90
12:20:01 AM 1289208 1790716 58.14 106580 1130096 1599588 44.38
12:30:01 AM 1248100 1831824 59.48 109184 1144680 1621332 44.98
12:40:01 AM 1267972 1811952 58.83 111460 1155828 1604104 44.51
12:50:01 AM 1254556 1825368 59.27 113888 1159632 1599480 44.38
01:00:01 AM 1092296 1987628 64.53 116020 1164540 1802228 50.00
01:10:01 AM 1212168 1867756 60.64 118204 1169516 1633940 45.33
...
Average: kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit
Average: 1465222 1614702 52.43 179213 834889 1655342 45.93
Uma atualização de RAM é necessária se o servidor mostrar uma utilização de memória consistentemente elevada ou se a média do dia for superior a 90%, porque uma utilização tão elevada pode, por vezes, esgotar a memória livre num servidor com muita carga. Numa máquina virtual, a pressão de memória prolongada resolve-se com mais RAM ou corrigindo a aplicação, nunca com swap.
Outra ferramenta útil para identificar os processos que consomem memória é o comando «top», que permite ordenar os processos em execução pela utilização de recursos.
root@server [~]# top -c
top - 18:41:45 up 109 days, 18:03, 5 users, load average: 1.30, 1.24, 1.24
Tasks: 544 total, 2 running, 541 sleeping, 0 stopped, 1 zombie
Cpu(s): 8.3%us, 1.4%sy, 0.2%ni, 89.8%id, 0.3%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 12296096k total, 11531800k used, 764296k free, 586732k buffers
Swap: 16777212k total, 209160k used, 16568052k free, 2471072k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2376001 root 20 0 230m 101m 4588 R 31.4 0.8 1:22.06 spamd child
2448741 root 30 10 19472 1056 792 S 2.6 0.0 0:00.08 /usr/sbin/lveps -c 1 -p -d -n -o id:10,ep:10,pno:10,pid:15,tno:5,tid:15,cpu:7,mem:15,com:256
953572 mysql 20 0 17.5g 5.3g 5336 S 1.7 44.9 102:38.10 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=server
844549 root 30 10 424m 59m 4532 S 1.3 0.5 52:13.20 /opt/alt/python27/bin/python2.7 /usr/share/lve-stats/lvestats-server.py start --pidfile /var/run/lvestats.pid
1351883 root 20 0 1127m 638m 1768 S 1.3 5.3 37:37.24 /usr/local/cpanel/3rdparty/bin/clamd
844526 root 30 10 462m 35m 1204 S 1.0 0.3 30:54.20 /opt/alt/python27/bin/python2.7 /usr/share/lve-stats/lvestats-server.py start --pidfile /var/run/lvestats.pid
3109 nscd 20 0 2725m 3956 2260 S 0.7 0.0 188:08.43 /usr/sbin/nscd
2243573 nobody 20 0 189m 78m 1140 S 0.7 0.7 4:22.20 litespeed (lshttpd - #01)
2448384 mailnull 20 0 78756 7736 3348 S 0.7 0.1 0:00.06 /usr/sbin/exim -bd -q1h -oP /var/spool/exim/exim-daemon.pid
Com a sequência de teclas abaixo ordena os processos pela utilização de memória.
Execute o comando top. Prima SHIFT+o para ver as opções do top. Prima N e Enter.
Identificar fugas de memória
Pode encontrar a hora do servidor em que o «out of memory» foi reportado, aqui “Mar 1 01:24:05”. Com o grep, procure essa marca temporal nos ficheiros de log dos seus servidores aplicacionais, como o Apache, o MySQL, etc.
Num servidor cPanel, pode usar o grep para procurar nos access logs dos websites acessos suspeitos ou abusivos que tenham causado este esgotamento de recursos.
grep -ir “01/Mar/2019:01:2” /usr/local/apache/domlogs/
Algumas atividades suspeitas identificáveis nos access logs:
- Acessos em grande número a partir de endereços IP específicos.
- Acessos em grande número a recursos ou ficheiros inexistentes, etc.
- Grande número de pedidos HTTP POST.
- Grande número de tentativas de acesso falhadas, como logins.
Use o comando mysqladmin proc stat para identificar queries MySQL que ficam penduradas durante muito tempo e causam uma utilização elevada de memória.
root@server [~]# mysqladmin proc stat
+--------+------+-----------+----+---------+------+-------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+--------+------+-----------+----+---------+------+-------+------------------+----------+
| 137324 | root | localhost | | Query | 0 | init | show processlist | 0.000 |
+--------+------+-----------+----+---------+------+-------+------------------+----------+
Uptime: 370827 Threads: 1 Questions: 20484133 Slow queries: 0 Opens: 1456 Flush tables: 1 Open tables: 747 Queries per second avg: 55.239
Verifique as colunas Time, db e State, encontre as queries com um valor de «Time» elevado e analise-as com o programador do seu website.
Ative o «Slow Query Logging» no MySQL e corrija as queries demoradas com o programador do seu website.
Memory overcommit
Normalmente, o servidor Linux permite reservar para um processo mais memória do que a que ele realmente precisa, partindo do princípio de que nenhum processo usará toda a memória que lhe é permitida, podendo essa memória ser usada por outros processos. É possível configurar a forma como o sistema Linux trata o memory overcommit, e a configuração aplica-se com a ferramenta sysctl.
Todos os parâmetros de controlo do sysctl podem ser listados com o comando sysctl -a, e o parâmetro que nos interessa é vm.overcommit_memory.
[root@srv ~]# sysctl -a | grep vm.overcommit_memory
vm.overcommit_memory = 0
O vm.overcommit_memory pode ter 3 valores: 0, 1 e 2.
- 0 Permite overcommit com base na estimativa «se tivermos RAM suficiente»
- 1 Permite sempre overcommit
- 2 Recusa overcommit se o sistema não tiver a memória.
Outro parâmetro sysctl a considerar é o overcommit_ratio, que define que percentagem da memória física, além do espaço de swap, pode ser considerada ao permitir que os processos façam overcommit.
Se definirmos vm.overcommit_memory como 2, o kernel não permite overcommit para além do espaço de swap mais o vm.overcommit_ratio da RAM total: vm.overcommit_memory=2 vm.overcommit_ratio=50% RAM=8GB SWAP=4GB
Com a configuração acima, o overcommit é possível para 4GB SWAP + 50% de 8GB RAM.
sysctl -w vm.overcommit_memory=2
sysctl -w vm.overcommit_ratio=100
O sysctl -w não sobrevive a um reinício. Coloque as mesmas duas linhas em /etc/sysctl.conf.
Das FAQ da EuroVPS.
Mais na categoria «Guias»O seu próximo parceiro de infraestrutura
Ainda tem
uma pergunta?
Diga-nos o que está a tentar fazer. Um engenheiro vai ler e responder.
+357 222 32280
Comecemos pela sua infraestrutura.
Um pouco de contexto ajuda-nos a começar a conversa certa.
