Como evitar os 10 principais erros de configuração do NGINX

NGINX | 22 de fevereiro de 2022

Quando ajudamos usuários do NGINX que estão enfrentando problemas, muitas vezes encontramos os mesmos erros de configuração que já vimos repetidamente nas configurações de outros usuários — às vezes, até mesmo em configurações escritas por outros engenheiros do NGINX! Neste blog, analisamos 10 dos erros mais comuns, explicando o que está errado e como corrigi-los.

  1. Descritores de arquivo insuficientes por worker
  2. A diretiva error_log off directive
  3. Não habilitar conexões keepalive com servidores upstream
  4. Esquecer como funciona a herança de diretivas
  5. A diretiva proxy_buffering off directive
  6. Uso inadequado da diretiva if directive
  7. Verificações de integridade excessivas
  8. Acesso não seguro às métricas
  9. Usar ip_hash quando todo o tráfego vem do mesmo bloco CIDR /24
  10. Não aproveitar os grupos de upstream

Erro 1: descritores de arquivo insuficientes por worker

A diretiva worker_connections define o número máximo de conexões simultâneas que um processo de trabalho do NGINX pode manter abertas (o padrão é 512). Todos os tipos de conexão (por exemplo, conexões com servidores de proxy) são contabilizados nesse limite, não apenas as conexões de clientes. No entanto, é importante ter em mente que há ainda outro limite para o número de conexões simultâneas por processo de trabalho: o limite do sistema operacional para o número máximo de descritores de arquivo (FDs) alocados a cada processo. Nas distribuições UNIX modernas, o limite padrão é 1024.

Para todas as implantações do NGINX, exceto as menores, um limite de 512 conexões por processo worker provavelmente é muito baixo. De fato, o arquivo padrão nginx.conf que distribuímos com os binários do NGINX Open Source e do NGINX Plus aumenta esse limite para 1024.

Um erro comum de configuração é não aumentar o limite de descritores de arquivo (FDs) para pelo menos o dobro do valor de worker_connections. Para corrigir isso, defina esse valor com a diretiva worker_rlimit_nofile no contexto principal da configuração.

Veja por que são necessários mais FDs: cada conexão de um processo de trabalho do NGINX com um cliente ou servidor upstream consome um FD. Quando o NGINX atua como servidor web, ele usa um FD para a conexão com o cliente e um FD para cada arquivo fornecido, totalizando no mínimo dois FDs por cliente (mas a maioria das páginas web é composta por muitos arquivos). Quando atua como servidor proxy, o NGINX usa um FD para a conexão com o cliente e outro para a conexão com o servidor upstream, além de possivelmente um terceiro FD para o arquivo usado para armazenar temporariamente a resposta do servidor. Como servidor de cache, o NGINX se comporta como um servidor web para respostas armazenadas em cache e como um servidor proxy se o cache estiver vazio ou tiver expirado.

O NGINX também usa um FD por arquivo de log e alguns FDs para se comunicar com o processo mestre, mas geralmente esses números são pequenos em comparação com a quantidade de FDs usados para conexões e arquivos.

O UNIX oferece várias maneiras de definir o número de descritores de arquivo (FDs) por processo:

  • O comando ulimit se você iniciar o NGINX a partir de um shell
  • O script init ou as variáveis do manifesto de serviço do systemd se você iniciar o NGINX como um serviço
  • O arquivo /etc/security/limits.conf file

No entanto, o método a ser usado depende de como você inicia o NGINX, enquanto worker_rlimit_nofile funciona independentemente de como você inicia o NGINX.

Há também um limite para todo o sistema quanto ao número de descritores de arquivo (FDs), que pode ser definido com o comando sysctl fs.file-max do sistema operacional. Esse limite geralmente é alto o suficiente, mas vale a pena verificar se o número máximo de descritores de arquivo que todos os processos de trabalho do NGINX podem usar (worker_rlimit_nofile * worker_processes) é significativamente menor que fs.file‑max. Se, por algum motivo, o NGINX usar todos os FDs disponíveis (por exemplo, durante um ataque de DoS), será impossível até mesmo fazer login na máquina para corrigir o problema.

Erro 2: A diretiva error_log off Directive

O erro comum é pensar que a diretiva error_log off desativa o registro de logs. Na verdade, diferentemente da diretiva access_log, error_log não aceita o parâmetro off. Se você incluir a diretiva error_log off na configuração, o NGINX criará um arquivo de log de erros chamado off no diretório padrão dos arquivos de configuração do NGINX (geralmente /etc/nginx).

Não recomendamos desabilitar o log de erros, pois ele é uma fonte essencial de informações para depurar quaisquer problemas com o NGINX. No entanto, se o armazenamento for tão limitado que o volume de dados registrados possa esgotar o espaço disponível em disco, talvez faça sentido desabilitar o registro de erros. Inclua esta diretiva no contexto principal da configuração:

error_log /dev/null emerg;

Observe que essa diretiva só entra em vigor depois que o NGINX lê e valida a configuração. Portanto, sempre que o NGINX for iniciado ou a configuração for recarregada, ele poderá registrar mensagens no local padrão do log de erros (geralmente /var/log/nginx/error.log) até que a configuração seja validada. Para alterar o diretório de logs, inclua o parâmetro -e <error_log_location> no comando nginx.

Erro 3: não habilitar conexões keepalive com servidores upstream

Por padrão, o NGINX abre uma nova conexão com um servidor upstream (backend) para cada nova solicitação recebida. Isso é seguro, mas ineficiente, pois o NGINX e o servidor precisam trocar três pacotes para estabelecer uma conexão e três ou quatro para encerrá-la.

Com grandes volumes de tráfego, abrir uma nova conexão para cada solicitação pode esgotar os recursos do sistema e impossibilitar completamente a abertura de conexões. Veja o motivo: para cada conexão, a quádrupla formada pelo endereço de origem, porta de origem, endereço de destino e porta de destino deve ser exclusiva. Nas conexões do NGINX com um servidor upstream, três desses elementos (o primeiro, o terceiro e o quarto) são fixos, restando apenas a porta de origem como variável. Quando uma conexão é encerrada, o socket do Linux permanece no estado TIME‑WAIT por dois minutos, o que, com grandes volumes de tráfego, aumenta a possibilidade de esgotar o conjunto de portas de origem disponíveis. Se isso acontecer, o NGINX não conseguirá abrir novas conexões com servidores upstream.

A solução é habilitar conexões keepalive entre o NGINX e os servidores upstream. Em vez de ser encerrada quando uma solicitação é concluída, a conexão permanece aberta para ser usada em outras solicitações. Isso reduz a possibilidade de esgotamento das portas de origem e também melhora o desempenho.

Para habilitar conexões keepalive:

  • Inclua a diretiva keepalive em cada bloco upstream{} para definir o número de conexões keepalive ociosas com servidores upstream que serão mantidas no cache de cada processo de trabalho. Observe que a diretiva keepalive não limita o número total de conexões com servidores upstream que um processo de trabalho do NGINX pode abrir — esse é um equívoco comum. Portanto, o parâmetro de keepalive não precisa ser tão grande quanto você imagina. Recomendamos definir o parâmetro como o dobro do número de servidores listados no bloco upstream{}. Esse valor é grande o suficiente para que o NGINX mantenha conexões keepalive com todos os servidores, mas pequeno o bastante para que os servidores upstream também possam processar novas conexões de entrada. Observe também que, ao especificar um algoritmo de balanceamento de carga no bloco upstream{} — com a diretiva hash, ip_hash, least_conn, least_time ou random —, ela deve aparecer antes da diretiva keepalive. Essa é uma das raras exceções à regra geral de que a ordem das diretivas na configuração do NGINX não importa.
  • No bloco location{} que encaminha solicitações para um grupo upstream, inclua as seguintes diretivas junto com a diretiva proxy_pass:
proxy_http_version 1.1;
proxy_set_header   "Connection" "";
  • Por padrão, o NGINX usa HTTP/1.0 para conexões com servidores upstream e, consequentemente, adiciona o cabeçalho Connection: close às solicitações que encaminha aos servidores. Como resultado, cada conexão é encerrada quando a solicitação é concluída, apesar da presença da diretiva keepalive no bloco upstream{}. A diretiva proxy_http_version instrui o NGINX a usar HTTP/1.1, enquanto a diretiva proxy_set_header remove o valor close do cabeçalho Connection.

Erro 4: esquecer como funciona a herança de diretivas

As diretivas do NGINX são herdadas de cima para baixo, ou “de fora para dentro”: um contexto filho — aninhado em outro contexto (seu contexto pai) — herda as configurações das diretivas incluídas no nível do contexto pai. Por exemplo, todos os blocos server{} e location{} no contexto http{} herdam o valor das diretivas incluídas no nível http, e uma diretiva em um bloco server{} é herdada por todos os blocos location{} filhos contidos nele. No entanto, quando a mesma diretiva é incluída tanto em um contexto pai quanto em seu contexto filho, os valores não são somados; em vez disso, o valor no contexto filho substitui o valor do contexto pai.

O erro é esquecer essa “regra de substituição” para as diretivas de matriz, que podem ser incluídas não apenas em vários contextos, mas também várias vezes em um mesmo contexto. Alguns exemplos são proxy_set_header e add_header — o fato de a segunda conter “add” no nome torna particularmente fácil esquecer a regra de substituição.

Podemos ilustrar como a herança funciona com este exemplo de add_header:

http {    
    add_header X-HTTP-LEVEL-HEADER 1;
    add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

    server {
        listen 8080;
        location / {
            return 200 "OK";
        } 
    }

    server {
        listen 8081;
        add_header X-SERVER-LEVEL-HEADER 1;

        location / {
            return 200 "OK";
        }

        location /test {
            add_header X-LOCATION-LEVEL-HEADER 1;
            return 200 "OK";
        }

        location /correct {
            add_header X-HTTP-LEVEL-HEADER 1;
            add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

            add_header X-SERVER-LEVEL-HEADER 1;
            add_header X-LOCATION-LEVEL-HEADER 1;
            return 200 "OK";
        } 
    }
}

Para o servidor que escuta na porta 8080, não há diretivas add_header nos blocos server{} nem location{}. Portanto, a herança é simples, e vemos os dois cabeçalhos definidos no contexto http{}:

% curl -i localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:15 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-HTTP-LEVEL-HEADER: 1 X-ANOTHER-HTTP-LEVEL-HEADER: 1
OK

Para o servidor que escuta na porta 8081, há uma diretiva add_header no bloco server{}, mas não no bloco filho location /. O cabeçalho definido no bloco server{} substitui os dois cabeçalhos definidos no contexto http{}:

% curl -i localhost:8081
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:20 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-SERVER-LEVEL-HEADER: 1
OK

No bloco filho location /test, há uma diretiva add_header que substitui tanto o cabeçalho do bloco pai server{} quanto os dois cabeçalhos do contexto http{}:

% curl -i localhost:8081/test
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:25 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-LOCATION-LEVEL-HEADER: 1
OK

Se quisermos que um bloco location{} preserve os cabeçalhos definidos nos contextos superiores, além dos cabeçalhos definidos localmente, precisaremos redefinir os cabeçalhos superiores dentro do bloco location{}. Foi isso que fizemos no bloco location /correct:

% curl -i localhost:8081/correct
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 21 Feb 2022 10:12:30 GMT
Content-Type: text/plain
Content-Length: 2
Connection: keep-alive
X-HTTP-LEVEL-HEADER: 1 X-ANOTHER-HTTP-LEVEL-HEADER: 1 X-SERVER-LEVEL-HEADER: 1 X-LOCATION-LEVEL-HEADER: 1
OK

Erro 5: A diretiva proxy_buffering off Directive

O buffering de proxy é habilitado por padrão no NGINX (a diretiva proxy_buffering é definida como on). O buffering de proxy significa que o NGINX armazena a resposta de um servidor em buffers internos à medida que ela é recebida e só começa a enviar dados ao cliente depois que toda a resposta tiver sido armazenada em buffer. O buffering ajuda a otimizar o desempenho com clientes lentos: como o NGINX mantém a resposta em buffer durante todo o tempo necessário para que o cliente a recupere por completo, o servidor com proxy pode retornar sua resposta o mais rápido possível e voltar a ficar disponível para atender a outras solicitações.

Quando o buffering de proxy está desabilitado, o NGINX armazena em buffer apenas a primeira parte da resposta de um servidor antes de começar a enviá-la ao cliente, em um buffer que, por padrão, tem o tamanho de uma página de memória (4 KB ou 8 KB, dependendo do sistema operacional). Normalmente, esse espaço é suficiente apenas para o cabeçalho da resposta. Em seguida, o NGINX envia a resposta ao cliente de forma síncrona à medida que a recebe, fazendo com que o servidor fique ocioso enquanto aguarda até que o NGINX possa aceitar o próximo segmento da resposta.

Por isso, ficamos surpresos com a frequência com que vemos proxy_buffering off nas configurações. Talvez a intenção seja reduzir a latência percebida pelos clientes, mas o efeito é insignificante, enquanto os efeitos colaterais são numerosos: com o buffering de proxy desativado, a limitação de taxa e o cache não funcionam mesmo quando configurados, o desempenho é prejudicado e assim por diante.

Há apenas um pequeno número de casos de uso em que desabilitar o buffering de proxy pode fazer sentido (como em long polling), portanto, não recomendamos alterar a configuração padrão. Para obter mais informações, consulte o Guia de Administração do NGINX Plus.

Erro 6: uso inadequado da diretiva if Directive

A diretiva if é difícil de usar, especialmente em blocos location{}. Muitas vezes, ela não faz o que você espera e pode até causar falhas de segmentação. Na verdade, ela é tão complicada que há um artigo intitulado If is Evil na Wiki do NGINX, e recomendamos que você o consulte para obter uma discussão detalhada sobre os problemas e como evitá-los.

Em geral, as únicas diretivas que você sempre pode usar com segurança dentro de um bloco if{} são return e rewrite. O exemplo a seguir usa if para detectar solicitações que incluem o cabeçalho X‑Test (mas essa pode ser qualquer condição que você queira testar). O NGINX retorna o erro 430 (Request Header Fields Too Large), intercepta-o no local nomeado @error_430 e encaminha a solicitação por proxy para o grupo upstream chamado b.

location / {    
    error_page 430 = @error_430;
    if ($http_x_test) {
        return 430; 
    }

    proxy_pass http://a;
}

location @error_430 {
    proxy_pass b;
}

Para este e muitos outros usos de if, muitas vezes é possível evitar completamente essa diretiva. No exemplo a seguir, quando a solicitação inclui o cabeçalho X‑Test, o bloco map{} define a variável $upstream_name como b e a solicitação é encaminhada por proxy para o grupo de upstream com esse nome.

map $http_x_test $upstream_name {    
    default "b";
    ""      "a";
}

# ...

location / {
    proxy_pass http://$upstream_name;
}

Erro 7: verificações de integridade excessivas

É bastante comum configurar vários servidores virtuais para encaminhar solicitações por proxy ao mesmo grupo de upstreams (em outras palavras, incluir a mesma diretiva proxy_pass em vários blocos server{}). O erro nessa situação é incluir uma diretiva health_check em cada bloco server{}. Isso apenas aumenta a carga nos servidores upstream sem fornecer nenhuma informação adicional.

Correndo o risco de dizer o óbvio, a solução é definir apenas uma verificação de integridade por bloco upstream{}. Aqui, definimos a verificação de integridade do grupo de upstream chamado b em um local nomeado especial, com as configurações adequadas de tempo limite e cabeçalhos.

location / {    
    proxy_set_header Host $host;
    proxy_set_header "Connection" "";
    proxy_http_version 1.1;
    proxy_pass http://b;
}

location @health_check {
    health_check;
    proxy_connect_timeout 2s;
    proxy_read_timeout 3s;
    proxy_set_header Host example.com;
    proxy_pass http://b;
}

Em configurações complexas, o gerenciamento pode ser ainda mais simplificado agrupando todos os locais de verificação de integridade em um único servidor virtual, juntamente com a API e o painel do NGINX Plus, como neste exemplo.

server {	
        listen 8080;
 
	location / {
	    # …
 	}
 
	location @health_check_b {
	    health_check;
	    proxy_connect_timeout 2s;
	    proxy_read_timeout 3s;
	    proxy_set_header Host example.com;
	    proxy_pass http://b;
	}
 
	location @health_check_c {
	    health_check;
	    proxy_connect_timeout 2s;
	    proxy_read_timeout 3s;
	    proxy_set_header Host api.example.com;
	    proxy_pass http://c;
	}
 
	location /api {
	    api write=on;
	    # directives limiting access to the API (see 'Mistake 8' below)
	}
 
	location = /dashboard.html {
	    root   /usr/share/nginx/html;
	}
}

Para obter mais informações sobre verificações de integridade de servidores HTTP, TCP, UDP e gRPC, consulte o NGINX Plus Admin Guide.

Erro 8: acesso não seguro às métricas

As métricas básicas sobre a operação do NGINX estão disponíveis no módulo Stub Status. Para o NGINX Plus, você também pode coletar um conjunto muito mais abrangente de métricas com a API do NGINX Plus. Habilite a coleta de métricas incluindo, respectivamente, a diretiva stub_status ou api em um bloco server{} ou location{}, que passa a ser a URL acessada para visualizar as métricas. (Para a API do NGINX Plus, também é necessário configurar zonas de memória compartilhada para as entidades do NGINX — servidores virtuais, grupos de upstream, caches e assim por diante — cujas métricas você deseja coletar; consulte as instruções no Guia de Administração do NGINX Plus.)

Algumas das métricas contêm informações confidenciais que podem ser usadas para atacar seu site ou os aplicativos que usam o NGINX como proxy. Um erro que às vezes encontramos nas configurações dos usuários é não restringir o acesso à URL correspondente. Aqui, veremos algumas maneiras de proteger as métricas. Usaremos stub_status nos primeiros exemplos.

Com a configuração a seguir, qualquer pessoa na Internet pode acessar as métricas em http://example.com/basic_status.

server {    
    listen 80;
    server_name example.com;

    location = /basic_status {
        stub_status;
    }
}

Proteja as métricas com autenticação HTTP básica

Para proteger as métricas com senha usando a Autenticação Básica HTTP, inclua as diretivas auth_basic e auth_basic_user_file. O arquivo (neste caso, .htpasswd) contém os nomes de usuário e as senhas dos clientes que podem fazer login para visualizar as métricas:

server {    
    listen 80;
    server_name example.com;

    location = /basic_status {
        auth_basic “closed site”;
        auth_basic_user_file conf.d/.htpasswd;
        stub_status;
    }
}

Proteja as métricas com as diretivas allow e deny Directives

Se você não quiser que os usuários autorizados precisem fazer login e souber os endereços IP a partir dos quais eles acessarão as métricas, outra opção será a diretiva allow. Você pode especificar endereços IPv4 e IPv6 individuais e intervalos CIDR. A diretiva deny all impede o acesso a partir de qualquer outro endereço.

server {    
    listen 80;
    server_name example.com;

    location = /basic_status {
        allow 192.168.1.0/24;
        allow 10.1.1.0/16;
        allow 2001:0db8::/32;
        allow 96.1.2.23/32;
        deny  all;
        stub_status;
    }
}

Combine os dois métodos

E se quisermos combinar os dois métodos? Podemos permitir que clientes acessem as métricas de endereços específicos sem uma senha e, ainda assim, exigir login de clientes provenientes de outros endereços. Para isso, usamos a diretiva satisfy any. Ela instrui o NGINX a permitir o acesso a clientes que façam login com credenciais de autenticação HTTP Basic ou estejam usando um endereço IP previamente aprovado. Para aumentar a segurança, você pode definir satisfy como all para exigir que até mesmo as pessoas provenientes de endereços específicos façam login.

server {    
    listen 80;
    server_name monitor.example.com;

    location = /basic_status {
        satisfy any;

        auth_basic “closed site”;
        auth_basic_user_file conf.d/.htpasswd;
        allow 192.168.1.0/24;
        allow 10.1.1.0/16;
        allow 2001:0db8::/32;
        allow 96.1.2.23/32;
        deny  all;
        stub_status;
    }
}

Com o NGINX Plus, você usa as mesmas técnicas para limitar o acesso ao endpoint da API do NGINX Plus (http://monitor.example.com:8080/api/ no exemplo a seguir), bem como ao painel de monitoramento de atividades em tempo real em http://monitor.example.com/dashboard.html.

Essa configuração permite o acesso sem senha apenas a clientes provenientes da rede 96.1.2.23/32 ou do localhost. Como as diretivas são definidas no nível de server{}, as mesmas restrições se aplicam tanto à API quanto ao painel. Vale observar que o parâmetro write=on de api permite que esses clientes também usem a API para fazer alterações na configuração.

Para obter mais informações sobre como configurar a API e o painel, consulte o Guia de Administração do NGINX Plus.

server {    
    listen 8080;
    server_name monitor.example.com;
 
    satisfy any;
    auth_basic “closed site”;
    auth_basic_user_file conf.d/.htpasswd;
    allow 127.0.0.1/32;
    allow 96.1.2.23/32;
    deny  all;

    location = /api/ {    
        api write=on;
    }

    location = /dashboard.html {
        root /usr/share/nginx/html;
    }
}

Erro 9: usar ip_hash quando todo o tráfego vem do mesmo bloco CIDR /24

O algoritmo ip_hash distribui a carga do tráfego entre os servidores em um bloco upstream{}, com base em um hash do endereço IP do cliente. A chave de hash corresponde aos três primeiros octetos de um endereço IPv4 ou ao endereço IPv6 completo. Esse método estabelece a persistência de sessão, o que significa que as solicitações de um cliente são sempre encaminhadas ao mesmo servidor, exceto quando ele está indisponível.

Suponha que tenhamos implantado o NGINX como proxy reverso em uma rede privada virtual configurada para alta disponibilidade. Colocamos vários firewalls, roteadores, balanceadores de carga de camada 4 e gateways à frente do NGINX para receber tráfego de diferentes origens (a rede interna, redes de parceiros, a Internet e assim por diante) e encaminhá-lo ao NGINX, que atua como proxy reverso para os servidores upstream. Esta é a configuração inicial do NGINX:

http {
    upstream {
        ip_hash;
        server 10.10.20.105:8080;
        server 10.10.20.106:8080;
        server 10.10.20.108:8080;
    }
 
    server {# …}
}

Mas há um problema: todos os dispositivos de “interceptação” estão na mesma rede 10.10.0.0/24, portanto, para o NGINX, parece que todo o tráfego vem de endereços nesse intervalo CIDR. Lembre-se de que o algoritmo ip_hash calcula o hash dos três primeiros octetos de um endereço IPv4. Em nossa implantação, os três primeiros octetos são os mesmos — 10.10.0 — para todos os clientes, portanto, o hash é igual para todos eles e não há como distribuir o tráfego entre servidores diferentes.

A solução é usar o algoritmo hash com a variável $binary_remote_addr como chave de hash. Essa variável captura o endereço completo do cliente, convertendo-o em uma representação binária de 4 bytes para um endereço IPv4 e 16 bytes para um endereço IPv6. Agora, o hash é diferente para cada dispositivo de interceptação, e o balanceamento de carga funciona conforme o esperado.

Também incluímos o parâmetro consistent para usar o método de hash ketama em vez do padrão. Isso reduz significativamente o número de chaves remapeadas para outro servidor upstream quando o conjunto de servidores muda, resultando em uma taxa de acertos de cache mais alta nos servidores de cache.

http {    
        upstream {
        hash $binary_remote_addr consistent;
        server 10.10.20.105:8080;
        server 10.10.20.106:8080;
        server 10.10.20.108:8080;
    }

    server {# …}
}

Erro 10: Não aproveitar os grupos upstream

Suponha que você esteja usando o NGINX em um dos casos de uso mais simples: como proxy reverso para uma única aplicação de backend baseada em NodeJS, que escuta na porta 3000. Uma configuração comum poderia ser assim:

http {
    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_set_header Host $host;
            proxy_pass http://localhost:3000/;
        }
    }
}

Bem simples, certo? A diretiva proxy_pass informa ao NGINX para onde enviar as solicitações dos clientes. Tudo o que o NGINX precisa fazer é resolver o nome do host para um endereço IPv4 ou IPv6. Depois que a conexão é estabelecida, o NGINX encaminha as solicitações para esse servidor.

O erro aqui é presumir que, como há apenas um servidor — e, portanto, não há motivo para configurar o balanceamento de carga —, não faz sentido criar um bloco upstream{}. Na verdade, um bloco upstream{} habilita vários recursos que melhoram o desempenho, como mostra esta configuração:

http {
    upstream node_backend {
        zone upstreams 64K;
        server 127.0.0.1:3000 max_fails=1 fail_timeout=2s;
        keepalive 2;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_set_header Host $host;
            proxy_pass http://node_backend/;
            proxy_next_upstream error timeout http_500;

        }
    }
}

A diretiva zone estabelece uma zona de memória compartilhada na qual todos os processos de trabalho do NGINX no host podem acessar informações de configuração e estado dos servidores upstream. Vários grupos upstream podem compartilhar a zona. Com o NGINX Plus, a zona também permite usar a API do NGINX Plus para alterar os servidores de um grupo upstream e as configurações de servidores individuais sem reiniciar o NGINX. Para obter detalhes, consulte o Guia de Administração do NGINX Plus.

A diretiva server tem vários parâmetros que podem ser usados para ajustar o comportamento do servidor. Neste exemplo, alteramos as condições que o NGINX usa para determinar que um servidor não está íntegro e, portanto, não está apto a aceitar solicitações. Aqui, ele considera um servidor não íntegro se uma tentativa de comunicação falhar uma única vez em cada período de 2 segundos (em vez do padrão de uma vez em um período de 10 segundos).

Estamos combinando essa configuração com a diretiva proxy_next_upstream para definir o que o NGINX considera uma tentativa de comunicação com falha, caso em que ele encaminha as solicitações para o próximo servidor no grupo upstream. Às condições padrão de erro e tempo limite, adicionamos http_500 para que o NGINX considere um código HTTP 500 (Erro Interno do Servidor) de um servidor upstream como uma tentativa com falha.

A diretiva keepalive define o número de conexões keepalive ociosas com servidores upstream que são mantidas no cache de cada processo de trabalho. Já discutimos os benefícios em Erro 3: não habilitar conexões keepalive com servidores upstream.

Com o NGINX Plus, você pode configurar recursos adicionais com grupos de upstream:

  • Mencionamos acima que o NGINX Open Source resolve os nomes de host dos servidores para endereços IP apenas uma vez, durante a inicialização. O parâmetro resolve da diretiva server permite que o NGINX Plus monitore alterações nos endereços IP correspondentes ao nome de domínio de um servidor upstream e modifique automaticamente a configuração do upstream sem a necessidade de reinicialização. O parâmetro service também permite que o NGINX Plus use registros DNS SRV, que incluem informações sobre números de porta, pesos e prioridades. Isso é essencial em ambientes de microsserviços, nos quais os números de porta dos serviços costumam ser atribuídos dinamicamente. Para obter mais informações sobre a resolução de endereços de servidores, consulte Uso do DNS para descoberta de serviços com NGINX e NGINX Plus em nosso blog.
  • O parâmetro slow_start da diretiva server permite que o NGINX Plus aumente gradualmente o volume de solicitações enviadas a um servidor que acaba de ser considerado íntegro e disponível para aceitar solicitações. Isso evita uma enxurrada repentina de solicitações que poderia sobrecarregar o servidor e fazer com que ele falhasse novamente.
  • A diretiva queue permite que o NGINX Plus coloque as solicitações em uma fila quando não for possível selecionar um servidor upstream para processá-las, em vez de retornar imediatamente um erro ao cliente.

Recursos

Para experimentar o NGINX Plus, comece hoje mesmo sua avaliação gratuita de 30 dias ou entre em contato conosco para conversar sobre seus casos de uso.


Compartilhar

Sobre o autor

Timo Stark
Timo StarkEngenheiro de Gestão de Produtos

Mais publicações de Timo Stark

Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
NGINX | 10/10/2024

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade

Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
NGINX | 17/06/2024

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa

Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
NGINX | 14/07/2021

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor

Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
NGINX | 02/04/2019

Distribuição segura de chaves privadas SSL com o NGINX

Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
NGINX | 24/05/2018

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX

O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
NGINX | 19/04/2016

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus

Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.