Tuning do Nginx

Pessoal vou compartilhar com vocês como eu faço para tunar o Nginx. Vamos abordar o tuning do sistema operacional e o tuning do Nginx.

Tuning do Sistema Operacional

O tuning do sistema operacional é configurado alterando-se parâmetros do kernel através do sysctl.

Configuração do sysctl

Edite o arquivo /etc/sysctl.conf
Ou crie um arquivo de configuração “.conf” em: /etc/sysctl.d/ (recomendado).
Exemplo: /etc/sysctl.d/tuninginx.conf

Abaixo seguem os parâmetros e uma breve descrição de cada um.

Prevenção de SYN Flood e ataques DDOS.
net.ipv4.tcp_syncookies = 1

Número de conexões aguardando a confirmação “ACK” do cliente.
Aumente conforme a necessidade do servidor.
net.ipv4.tcp_max_syn_backlog = 65535

Quantas vezes tentar retransmitir uma resposta SYN-ACK.
net.ipv4.tcp_synack_retries = 2

Quantas vezes tentar retransmitir uma resposta SYN.
net.ipv4.tcp_syn_retries = 2

Tempo de espera pela resposta de encerramento FIN-WAIT. Em resumo tempo máximo para esperar
o encerramento de uma conexão.
net.ipv4.tcp_fin_timeout = 15

Número máximo de conexões enfileiradas. Isto afeta o número máximo de conexões e pacotes de entrada.
Tem que ser menor que a quantidade de file descriptors.
net.core.somaxconn = 65535

Número máximo de pacotes que podem ser enfileirados na placa de rede antes do processamento. Quanto maior a banda de rede melhor.
net.core.netdev_max_backlog = 65535

File Descriptors controlam a quantidade de processos e arquivos que um usuário pode trabalhar no Linux.
Configuração global, ou seja afeta todo o sistema.
fs.file-max = 185032

[root@lemp-01 sysctl.d]# cat /etc/sysctl.d/tuninginx.conf 
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_synack_retries = 2 
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_fin_timeout = 15
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
fs.file-max = 185032
Configuração do file descriptor por usuário

Pode ser configurado tanto na pasta /etc/security/limits.d/ no arquivo limits.conf.

#vi /etc/security/limits.conf
nginx                soft   nofile      8192
nginx                hard   nofile      65835

Tuning do Nginx

O tuning do Nginx é configurado alterando-se parâmetros de configuração no arquivo nginx.conf. Também é possível configurar alguns parâmetros no virtual host.

#vi /etc/nginx/nginx.conf

worker_rlimit_nofile – contexto: main – Limita o número máximo de openfiles.
worker_rlimit_nofile 65535;

worker_processes – contexto: main – Quantos processos serão carregados. O ideal é um processo por cpu.
Por ex: 8 cpus=worker_processes=8. A opção “auto” configura automaticamente os processos.
worker_processes auto;

worker_connections – contexto: events – quantidade de conexões por processo.
#não pode exceder a quantidade de File Descriptors.
#aumente conforme a necessidade e capacidade.
worker_connections = 8190;

accept_mutex – contexto: events – Economiza recursos do sistema destinado aos worker processes.
Se ativo worker process receberão as conexões por turno, caso contrário todos os worker processes serão notificados sobre novas conexões, e atenderá aquele que tiver livre.
accept_mutex off;

Epoll – contexto: events – Método de conexão para kernel >= 2.6. Epoll é utilizado em ambientes que precisam escalar com eficiência, que precisam de muitos file descriptors abertos.
use epoll;

multi_accept – contexto: events – Se desabilitado o worker process vai aceitar uma conexão por vez, caso contrário o worker process vai aceitar todas as conexões ao mesmo tempo.
multi_accept on;

Parâmetros sendfile, tcp_nopush e tcp_nodelay

Não tenha dúvidas que no tuning do Nginx os parâmetros sendfile, tcp_nodelay e tcp_nopush são os que geram maior confusão.

Sendfile pode ser utilizado ou não, depende do ambiente.

Sendfile – contexto http, server, location, if in location – Permite a transferência de dados de um File Descriptor a outro diretamente no Kernel.
Substitui a operação de leitura e escrita em um File Descriptor.
Execução diretamente no kernel sem a troca de contexto.
Escrita diretamente no Buffer do Kernel (DMA).
Recomendado para servir arquivos estáticos (cache).
Se o servidor for um proxy reverso ou apenas web server pode ser desativado.
sendfile on;

tcp_nodelay – contexto http, server, location – Elimina ou ativa o delay de 200ms na pilha TCP para que um dado possa ser enviado. Quando ativado “On” um pacote será enviado assim que tiver disponível e não mais após o tempo de 200ms.
tcp_nodelay on;

tcp_nopush – contexto http, server, location – Controla o tamanho de um pacote antes do envio. Quando ativado “on” – o pacote será enviado somente com o tamanho MSS (MSS = MTU – IP header).
Quando “on” a opção sendfile precisa obrigatoriamente estar ativa “sendfile on”.
Quando desativado “off” o pacote será enviado assim que tiver pronto para ser enviado independentemente do tamanho, sem passar pelo bloqueio de tamanho MSS.
Quando Nginx configurado como servidor de Cache é interessante ligar o tcp_nopush, já que ao enviar apenas pacotes completos, diminui o tráfego de pequenos pacotes.
tcp_nopush off;

Combinações:
sendfile on + tcp_nopush on = Vai garantir um pacote completo antes do envio diminuindo o overhead de rede. Ideal para o Ngix como servidor de cache.

sendfile on + tcp_nopush on + tcp_nodelay on = Garante um pacote completo e menos overhead na rede. O pacote será enviado assim que disponível sem o bloqueio de 200ms.

tcp_nopush off + tcp_nodelay on = Um pacote será enviado assim que tiver disponível. Recomendado caso o Nginx seja apenas um web server ou proxy server (Sem qualquer função de cache).

sendfile off + tcp_nodelay on = o pacote será enviado assim que tiver disponível, sem delay de 200ms, melhor para web server ou proxy server, sem a troca de arquivos entre File Descriptors.

sendfile on + tcp_nodelay on = o pacote será enviado assim que tiver pronto, sem delay, melhor para web server ou proxy server, com a troca de arquivos entre File Descriptors.

Sugestões:
Para servidor de Cache = sendfile on + tcp_nopush on + tcp_nodelay on
Proxy Server = sendfile off + tcp_nopush off + tcp_nodelay on
Web server = sendfile (talvez on ou off) + tcp_nopush off + tcp_nodelay on
Para Web server é interessante testar a performance com sendfine on ou off.

O interessante é você combinar as opções e ir testando, no geral tcp_nopush e tcp_nodelay não combinam devido à natureza da coisa, o tcp_nopush controla o tamanho do pacote, e tcp_nodelay o tempo de envio do pacote.

Sendfile on combina bem tanto com o “tcp_nopush on” como o “tcp_nodelay on” porém dependendo do tipo de servidor (Proxy server) pode ser necessário desativar.

KeepAlive
keepalive_requests – contexto: http, server, location
– Quantas requisições um cliente pode fazer dentro de uma conexão keepalive.
keepalive_requests 100;

keepalive_timeout – contexto: http, server, location – Quanto tempo uma conexão com status idle em keepalive deve ser mantida aberta.
keepalive_timeout 65;

Desativar o Log, manter ligado ou deixar no buffer?

O log é o seguinte, a cada hit http no Nginx é logado sendo assim o Log consome muitos ciclos de I/O e processamento, em um ambiente de cache isto pode ser complicado, já que um servidor de cache utiliza muito I/O, então existirá concorrência.

Você tem que saber se precisa desligar o log ou não, em termos de performance com certeza desligar o log é o ideal.

Para melhor performance
access_log off;

Porém se mesmo assim você quer manter o log ativo, eu particularmente gosto de log, então você pode tentar minimizar o impacto de I/O e colocar o log para ser gravado no buffer, e assim que o buffer tiver cheio o log será gravado no disco em uma tacada só, e assim sucessivamente.
access_log /var/log/nginx/access.log main buffer=64k;

Ou simplesmente deixe o log padrão
access_log /var/log/nginx/access.log main;

#cat /etc/nginx/nginx.conf

user  nginx;
worker_processes  auto;
worker_rlimit_nofile 65535;

error_log  /var/log/nginx/error.log debug;
pid        /var/run/nginx.pid;

events {
    worker_connections  8190;
    accept_mutex  off;
    use epoll;
    multi_accept on;
    
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log  /var/log/nginx/access.log main buffer=64k;

    sendfile     on;
    tcp_nopush   off;
    tcp_nodelay  on;
    keepalive_timeout  65;
    keepalive_requests  100;

    include /etc/nginx/conf.d/*.conf;
}

Tem muiiito mais coisas possíveis para se fazer, obviamente eu jamais conseguiria esgotar todo o assunto de tuning do Nginx, até mesmo por que cada ambiente precisa de configurações particulares, mas fica aqui mais algumas sugestões:

->Cache em memória RAM: se você está configurando um servidor de cache de imagens, considere montar o volume de cache na memória Ram (tmpfs). Escrever direto na memória RAM é rápido demais.

->Gzip on: Utilização de compressão de dados com gzip.

Print Webinar Nginx
Segue um print que eu tirei de um Webinar que tem no próprio site do Nginx https://www.nginx.com/resources/webinars/installing-tuning-nginx/
Assunto: instalação e Tuning do Nginx. Veja que tem mais algumas opções de Kernel e Nginx que podem ser tunadas.

webinar-nginxtuning

Nginx Benchmarking

Não adianta você fazer o tuning e não medir para ver se obteve melhoria ou piora de desempenho.
Existem várias ferramentas, das simples as complexas para medir o desempenho, eu vou sugerir uma bem simples de usar que é a “AB – ApacheBench” para a simulação de acessos web.

Também é interessante gerar gráficos para uma melhor mensuração, você pode experimentar a Gnuplot.
Com “AB – Apachebench + Gnuplot” você já consegue ter uma boa visão do seu tuning.

Bom é isto, o segredo do tuning é você ir alterando aos poucos e medindo com as ferramentas de Benchmarking, eu nunca vi na minha vida uma receita perfeita de tuning, as vezes algo que funciona bem em um ambiente, em outros já não funciona de forma tão eficiente.

Referências:
https://www.nginx.com/resources/webinars/installing-tuning-nginx/
https://www.nginx.com/blog/tuning-nginx/
https://www-01.ibm.com/support/knowledgecenter/linuxonibm/liaag/wp64bit/l0wpbt00_ds_linux_kernel_settings.htm
https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
http://www.revsys.com/12days/nginx-tuning/
https://t37.net/nginx-optimization-understanding-sendfile-tcp_nodelay-and-tcp_nopush.html
https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:config:mitigating-syn-floods
https://klaver.it/linux/sysctl.conf