Fragmentação de sockets no NGINX 1.9.1

NGINX | 26 de maio de 2015

NGINX 1.9.1 apresenta um novo recurso que permite o uso da opção de socket SO_REUSEPORT, disponível nas versões mais recentes de diversos sistemas operacionais, incluindo DragonFly BSD e Linux (versão 3.9 ou posterior do kernel). Essa opção permite que vários sockets escutem na mesma combinação de endereço IP e porta. Em seguida, o kernel distribui as conexões recebidas entre os sockets.

Editor – Para usuários do NGINX Plus, esse recurso é compatível com o NGINX Plus Release 7 (R7) e versões posteriores. Para ter uma visão geral de todos os novos recursos dessa versão, consulte Anúncio do NGINX Plus R7 em nosso blog.

A opção de soquete SO_REUSEPORT tem muitas aplicações práticas em potencial. Outros serviços podem usá-la para facilitar atualizações graduais de executáveis (o NGINX já oferece suporte a atualizações graduais por outros meios). No NGINX, habilitar essa opção de soquete pode melhorar o desempenho em determinados cenários, reduzindo a contenção de bloqueios.

Como mostrado na figura, quando a opção SO_REUSEPORT não está habilitada, um único soquete de escuta notifica os processos de trabalho sobre as conexões recebidas, e cada processo tenta aceitar uma conexão.

Com a opção SO_REUSEPORT habilitada, há vários sockets de escuta para cada combinação de endereço IP e porta, um para cada processo de trabalho. O kernel determina qual socket de escuta disponível (e, consequentemente, qual processo de trabalho) recebe a conexão. Isso pode reduzir a contenção de bloqueios entre os processos de trabalho que aceitam novas conexões e melhorar o desempenho em sistemas com vários núcleos. No entanto, isso também pode significar que, quando um processo de trabalho fica paralisado por uma operação bloqueante, o bloqueio afeta não apenas as conexões que ele já aceitou, mas também as solicitações de conexão que o kernel atribuiu a ele desde que ficou bloqueado.

Configurando o particionamento de sockets

Para habilitar a opção de soquete SO_REUSEPORT, inclua o novo parâmetro reuseport na diretiva listen para tráfego HTTP ou TCP (módulo stream), como nestes exemplos:

http {     server {
          listen 80 reuseport;
          server_name  localhost;
          # ...
     }
}

stream {
     server {
          listen 12345 reuseport;
          # ...
     }
}

A inclusão do parâmetro reuseport também desabilita a diretiva accept_mutex para o soquete, pois o mutex é redundante quando se usa reuseport. Ainda pode valer a pena definir accept_mutex se houver portas nas quais você não define reuseport.

Avaliando o desempenho com reuseport

Executei um wrk de benchmark com 4 workers do NGINX em uma instância da AWS com 36 núcleos. Para eliminar os efeitos da rede, executei o cliente e o NGINX no localhost e também configurei o NGINX para retornar a string OK em vez de um arquivo. Comparei três configurações do NGINX: a padrão (equivalente a accept_mutex on), com accept_mutex off e com reuseport. Como mostra a figura, reuseport aumenta o número de solicitações por segundo de 2 a 3 vezes e reduz tanto a latência quanto o desvio padrão da latência.

benchmark de reuseport

Também executei um benchmark relacionado, com o cliente e o NGINX em hosts separados e o NGINX retornando um arquivo HTML. Como mostra a tabela a seguir, com reuseport, a redução da latência foi semelhante à do benchmark anterior, e o desvio padrão diminuiu de forma ainda mais expressiva (quase dez vezes). Outros resultados (não mostrados na tabela) também foram animadores. Com reuseport, a carga foi distribuída uniformemente entre os processos de trabalho. Na configuração padrão (equivalente a accept_mutex on), alguns processos receberam uma porcentagem maior da carga e, com accept_mutex off, todos os processos ficaram sujeitos a uma carga elevada.

Latência (ms) Desvio padrão da latência (ms) Carga da CPUPadrão 15.65 26.59 0.3accept_mutex off 15.59 26.48 10reuseport 12.35 3.15 0.3

Nesses benchmarks, a taxa de solicitações de conexão é alta, mas as solicitações não exigem processamento intensivo. Outros testes preliminares também indicam que reuseport melhora mais o desempenho quando o tráfego corresponde a esse perfil. (O parâmetro reuseport não está disponível na diretiva listen no contexto mail, por exemplo, porque o tráfego de e-mail definitivamente não corresponde a esse perfil.) Recomendamos que você teste reuseport para determinar se ele melhora o desempenho na sua implantação do NGINX, em vez de aplicá-lo indiscriminadamente. Para ver algumas dicas sobre como testar o desempenho do NGINX, confira a palestra de Konstantin Pavlov na nginx.conf 2014.

Agradecimentos

Agradecemos a Yingqi Lu, da Intel, e a Sepherosa Ziehau, que contribuíram, cada um, com uma solução para o projeto NGINX que permite o uso da opção de soquete SO_REUSEPORT. A equipe do NGINX combinou ideias de ambas as contribuições para criar o que acreditamos ser uma solução ideal.


Compartilhar

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.