BLOG | NGINX

Registrando tráfego entre NGINX e servidores upstream em CDN77

NGINX-Parte-de-F5-horiz-preto-tipo-RGB
Miniatura de Vojtěch Štafa
Vojtěch Štafa
Publicado em 12 de dezembro de 2018

Independentemente da plataforma que você está executando, o registro geralmente é um requisito essencial para processamento de big data, estatísticas, auditorias, relatórios de clientes e transações, bem como para depuração de comunicação cliente-servidor e possíveis problemas.

Neste blog, abordamos o papel do registro na depuração, onde ele fornece a ferramenta definitiva para localizar os vários problemas tão comuns nas comunicações pela Internet.

Registro com uma conexão de direção entre cliente e servidor web

O registro da comunicação cliente-servidor web ajuda muito na depuração de possíveis problemas relacionados à versão do navegador, à rede do cliente e aos arquivos acessados. Mas não termina aí. Há infinitas possibilidades do que registrar, dependendo inteiramente da sua plataforma e requisitos.

Arquitetura de registro do NGINX

Ao executar um proxy reverso, balanceador de carga ou rede de distribuição de conteúdo (CDN), você está adicionando outro nó ao fluxo de comunicação entre cliente e servidor. Um servidor intermediário que manipula dados, como um proxy reverso, geralmente apresenta problemas inesperados.

Como um proxy reverso, o NGINX converte a conexão do cliente para o servidor web (ou outro servidor de aplicativo) em duas conexões separadas, encerrando a conexão do cliente e criando uma nova para o servidor. A “divisão” em duas conexões também cria dois contextos separados para registro, e o NGINX oferece suporte ao registro para eles de forma um pouco diferente.

  • Para o tráfego entre o cliente e o proxy reverso, o NGINX fornece um log de erros e um log de acesso , que registra eventos de processamento e ações que não são erros.

    Você habilita o log de erros com a diretiva error_log e pode definir o nível de gravidade dos erros a serem registrados.

    Você habilita o log de acesso com a diretiva access_log . A diretiva log_format associada permite que você personalize o tipo de informação incluída nos logs e o formato das entradas de log. Você pode gravar os logs em um arquivo, no syslog ou em ambos.

  • Para tráfego entre o proxy reverso e o servidor web ou de aplicativo (ao qual o NGINX se refere como servidor upstream ), o NGINX suporta o log de erros. No entanto, ele não oferece suporte ao registro de acesso para esse tráfego.

    A única maneira de ver eventos sem erro entre o servidor proxy e um servidor upstream é definir o nível de gravidade no log de erros como debug . A desvantagem dessa configuração é que grandes quantidades de dados são registradas. Isso retarda o processamento de solicitações e cria arquivos muito grandes que podem rapidamente ocupar o espaço de armazenamento. (Observe que você também deve recompilar o NGINX com o argumento --with-debug no comando configure , pois o suporte para depuração não está habilitado por padrão.)

Nossa solução de log upstream

Como provedores de CDN, frequentemente encontramos servidores upstream que não estão se comunicando corretamente com nossos servidores proxy reverso e clientes. As mensagens de nível de depuração no log de erros nem sempre fornecem o tipo de informação necessária para corrigir um problema com o servidor upstream.

A solução logo se tornou bastante evidente: gerar um log de acesso upstream adicionando uma função que reúne apenas as informações essenciais da comunicação entre o proxy reverso e os servidores upstream.

Registro com uma conexão dividida entre cliente e servidor web

A ideia geral é fazer com que o NGINX chame nossa função toda vez que uma solicitação a um servidor upstream for feita. Isso nos permite programar toda a lógica relacionada ao registro upstream na própria função.

O ngx_http_upstream_module padrão manipula solicitações upstream e precisamos que ele chame a função para nós. Atualmente, o módulo não oferece suporte a essa funcionalidade, então o corrigimos para habilitar o retorno de chamada quando necessário.

O registro em si é tratado em um módulo separado que escrevemos, que usa o recurso de retorno de chamada de registro que adicionamos no módulo upstream corrigido. O novo módulo define uma nova diretiva upstream_log para configurar a funcionalidade de registro. A diretiva usa o mesmo analisador que a diretiva access_log , então os dados podem ser gravados em um arquivo ou enviados para um servidor syslog usando um soquete.

Quando o NGINX lê a diretiva upstream_log em nginx.conf durante a inicialização, duas funções são chamadas:

  • ngx_http_upstream_log_set_log , que analisa a diretiva e prepara a própria estrutura de log ( ngx_log_t ) usando ngx_log_set_log internamente
  • ngx_http_upstream_log_init (em uma etapa de pós-configuração), que registra nossa função de registro principal com o módulo upstream

Dessa forma, quando uma solicitação precisa ser enviada por proxy para o upstream, tudo está pronto. O módulo upstream inicia uma conexão com o servidor upstream, e nosso patch garante que a função de registro seja chamada para registrar os detalhes da solicitação.

O formato de log é integrado ao módulo upstream. Ainda temos a opção de adicionar suporte para configuração usando a diretiva log_format , mas isso não é necessário para nosso caso de uso.

Valores registrados do Upstream

A função de registro é chamada logo após o fechamento da conexão com o servidor upstream. Seu argumento é um ponteiro para uma solicitação atualmente processada (a estrutura ngx_http_request_t ), que permite que a função acesse e registre todos os dados na estrutura. O campo upstream (ponteiro para ngx_http_upstream_t ) é de particular interesse, pois contém dados sobre a solicitação upstream. Estamos particularmente interessados em:

  • O código de status da resposta de origem
  • A duração do pedido
  • O valor de um cabeçalho HTTP em resposta ou cabeçalho de host

O acesso a toda a estrutura da solicitação é o que dá flexibilidade ao módulo, pois uma grande variedade de informações pode ser registrada.

Problemas que encontramos

Inicialmente implementamos a funcionalidade em ngx_http_core_module . Isso era bom o suficiente para um protótipo, mas não era uma solução muito limpa, pois poderia complicar futuras atualizações e modificações. Por fim, separamos a função de registro upstream em um módulo autônomo, conforme descrito em Nossa solução de registro upstream .

É claro que houve alguns problemas de implementação. Mais notavelmente, em alguns lugares nós manipulamos incorretamente as strings ngx_str_t , por exemplo, usando a função de biblioteca C sprintf em vez de ngx_snprintf . Isso pode causar a gravação de dados indefinidos no log upstream ou até mesmo uma falha de segmentação no thread de trabalho. Esses problemas foram resolvidos após extensa depuração e testes usando ferramentas como Valgrind e AddressSanitizer.

Recursos do NGINX usados no CDN77

O principal motivo pelo qual o CDN77 usa o NGINX é por seus recursos de cache. O servidor CDN é um nó introduzido entre o cliente e o servidor web (servidor upstream), transmitindo solicitações do cliente e solicitando arquivos apropriados do servidor upstream. Quando o arquivo é armazenado em cache, ele é entregue a outros usuários que solicitam o mesmo arquivo do mesmo local.

“Arquivos servidos localmente” é um dos recursos que estamos usando para que o NGINX forneça um arquivo do disco do servidor quando ele recebe uma solicitação.

Alguns recursos e configurações adicionais são necessários para o armazenamento em cache seguro. Utilizamos SSL (TLS 1.3 com 0‑RTT) ou tokens seguros que podem ser gerados para um endereço IP específico para proteger o conteúdo adequadamente.

Outros recursos que usamos incluem páginas de erro personalizadas para nossos clientes, a implementação padrão NGINX de grampeamento OCSP e FastCGI para PHP para reduzir o número de processos PHP necessários.

Conclusão

O registro upstream não apenas nos ajudou e continua ajudando na depuração de vários problemas, mas também forneceu uma excelente oportunidade para nos aprofundarmos mais na funcionalidade principal do NGINX e simplificou vários outros projetos que realizamos.

Sobre CDN77

O CDN77 torna a entrega de conteúdo melhor e mais conveniente em todo o mundo. Com mais de 30 data centers, somos capazes de armazenar em cache e entregar conteúdo de forma eficaz em todo o mundo. Isso inclui conteúdo estático em seu site, distribuição de software, vídeo sob demanda (VoD) e transmissão ao vivo por meio de vários protocolos, como HLS ou MPEG-DASH, usando um mecanismo de transmissão dedicado.

Começar a usar o CDN77 é muito fácil, rápido e direto. Inscreva-se para um teste gratuito , crie um recurso CDN e use o URL CDN gerado ou o registro CNAME personalizado para integrá-lo ao seu site ou solução de streaming. Todos os recursos, configurações e possíveis soluções personalizadas garantem que o CDN77 atenda às suas necessidades.


"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."