BLOG | NGINX

Maximizando o desempenho do Python com NGINX, Parte 1: Serviço Web e Cache

NGINX-Parte-de-F5-horiz-preto-tipo-RGB
Miniatura de Floyd Smith
Floyd Smith
Publicado em 31 de março de 2016

Introdução – Como o NGINX é usado com Python

O Python é famoso por ser fácil e divertido de usar, por facilitar o desenvolvimento de software e pelo desempenho de tempo de execução que, segundo se diz, excede o de outras linguagens de script. (Embora a versão mais recente do PHP, PHP 7, possa dar trabalho ao Python.)

Todo mundo quer que seu site e aplicativo funcionem mais rápido. Além disso, todo site com tráfego crescente ou picos repentinos de tráfego é vulnerável a problemas de desempenho e tempo de inatividade, geralmente ocorrendo nos piores momentos, ou seja, nos mais movimentados. Além disso, quase todos os sites sofrem problemas de desempenho e tempo de inatividade, independentemente se o volume de tráfego está crescendo de forma constante ou se há picos acentuados de uso.

É aí que entram o NGINX e o NGINX Plus. Eles melhoram o desempenho do site de três maneiras diferentes:

  1. Como um servidor web , o NGINX foi originalmente desenvolvido para resolver o problema C10K , ou seja, para suportar facilmente 10.000 ou mais conexões simultâneas. Usar o NGINX como servidor web para seu aplicativo Python torna seu site mais rápido, mesmo em níveis baixos de tráfego. Quando você tem milhares de usuários, é praticamente certo que você terá um desempenho muito melhor, menos travamentos e menos tempo de inatividade. Você também pode fazer cache de arquivos estáticos ou microcache no seu servidor web NGINX, embora ambos funcionem melhor quando executados em um servidor proxy reverso NGINX separado (veja o próximo parágrafo).
  2. Como um servidor proxy reverso – Você pode “colocar o NGINX” como um servidor proxy reverso na frente da configuração atual do seu servidor de aplicativos. O NGINX está voltado para a Web e passa solicitações para seu servidor de aplicativos. Este “truque estranho” faz seu site rodar mais rápido, reduz o tempo de inatividade, consome menos recursos do servidor e melhora a segurança. Você também pode armazenar em cache arquivos estáticos no servidor proxy reverso (muito eficiente), adicionar microcache de conteúdo dinâmico para reduzir a carga no próprio aplicativo e muito mais.
  3. Como um balanceador de carga para vários servidores de aplicativos – Comece implantando um servidor proxy reverso. Em seguida, dimensione executando vários servidores de aplicativos em paralelo e usando o NGINX ou o NGINX Plus para balancear a carga do tráfego entre eles. Com esse tipo de implantação, você pode facilmente dimensionar o desempenho do seu site de acordo com os requisitos de tráfego, aumentando a confiabilidade e o tempo de atividade. Se você precisar que uma determinada sessão de usuário permaneça no mesmo servidor, configure o balanceador de carga para oferecer suporte à persistência de sessão .

O NGINX e o NGINX Plus trazem vantagens, quer você os use como um servidor web para seu aplicativo Python, como um servidor proxy reverso, como um balanceador de carga ou para todas as três finalidades.

Neste primeiro artigo de uma série de duas partes, descrevemos cinco dicas para melhorar o desempenho de seus aplicativos Python, incluindo o uso do NGINX e do NGINX Plus como um servidor web, como implementar o cache de arquivos estáticos e o microcache de arquivos gerados pelo aplicativo. Na Parte 2 , descreveremos como usar o NGINX e o NGINX Plus como um servidor proxy reverso e como um balanceador de carga para vários servidores de aplicativos.

Dica 1 – Encontre gargalos de desempenho do Python

Existem duas condições muito diferentes nas quais o desempenho do seu aplicativo Python importa: primeiro, com números diários e “razoáveis” de usuários; e segundo, sob cargas pesadas. Muitos proprietários de sites se preocupam muito pouco com o desempenho sob cargas leves, quando – em nossa humilde opinião – eles deveriam estar suando a cada décimo de segundo em tempo de resposta. Reduzir milissegundos nos tempos de resposta é um trabalho difícil e ingrato, mas deixa os usuários mais felizes e os resultados comerciais melhores.

No entanto, esta postagem do blog e a Parte 2 que a acompanha concentram-se no cenário com o qual todos se preocupam: problemas de desempenho que ocorrem quando um site fica ocupado, como grandes lentidões e travamentos. Além disso, muitos ataques de hackers imitam os efeitos de aumentos repentinos no número de usuários, e melhorar o desempenho do site geralmente é um passo importante para lidar com os ataques também.

Com um sistema que aloca uma certa quantidade de memória por usuário, como o Apache HTTP Server, adicionar usuários faz com que a memória física fique sobrecarregada à medida que mais e mais usuários entram. O servidor começa a trocar para o disco, o desempenho cai e ocorrem falhas e desempenho ruim. A migração para o NGINX, conforme descrito nesta postagem do blog, ajuda a resolver esse problema.

Python é particularmente propenso a problemas de desempenho relacionados à memória, porque geralmente usa mais memória para realizar suas tarefas do que outras linguagens de script (e as executa mais rapidamente como resultado). Portanto, se todas as outras coisas forem iguais, seu aplicativo baseado em Python pode “cair” sob uma carga de usuário menor do que um aplicativo escrito em outra linguagem.

Otimizar seu aplicativo pode ajudar um pouco, mas geralmente não é a melhor ou mais rápida maneira de resolver problemas de desempenho do site relacionados ao tráfego. As etapas nesta postagem do blog e na Parte 2 que a acompanha são as melhores e mais rápidas maneiras de resolver problemas de desempenho relacionados ao tráfego. Então, depois de seguir os passos dados aqui, volte e melhore seu aplicativo ou reescreva-o para usar uma arquitetura de microsserviços .

Dica 2 – Escolha a implantação de servidor único ou multiservidor

Sites pequenos funcionam bem quando implantados em um único servidor. Sites grandes exigem vários servidores. Mas se você estiver na área cinzenta intermediária – ou se seu site estiver crescendo de um site pequeno para um grande – você tem algumas escolhas interessantes a fazer.

Se você tiver uma implantação de servidor único, estará correndo um risco significativo se tiver picos de tráfego ou rápido crescimento geral do tráfego. Sua escalabilidade é limitada, com possíveis correções que incluem melhorar seu aplicativo, mudar seu servidor web para NGINX, obter um servidor maior e mais rápido ou descarregar armazenamento para uma rede de distribuição de conteúdo (CDN). Cada uma dessas opções leva tempo para ser implementada, tem um custo e corre o risco de introduzir bugs ou problemas na implementação.

Além disso, com a implantação de servidor único, seu site, por definição, tem um único ponto de falha – e muitos dos problemas que podem tirar seu site do ar não têm soluções rápidas ou simples.

NGINX e Python trabalham juntos para fornecer desempenho por meio dos recursos do NGINX em serviços da Web, balanceamento de carga e armazenamento em cache
“Colocando o NGINX na frente” dos servidores de aplicação

Se você mudar seu servidor para NGINX em uma implantação de servidor único, poderá escolher livremente entre NGINX Open Source e NGINX Plus. O NGINX Plus inclui suporte de nível empresarial e recursos adicionais . Alguns dos recursos adicionais, como monitoramento de atividade ao vivo , são relevantes para uma implantação de servidor único, e outros, como balanceamento de carga e persistência de sessão , entram em jogo se você usar o NGINX Plus como um servidor proxy reverso em uma implantação de vários servidores.

Considerando tudo isso, a menos que você tenha certeza de que seu site permanecerá pequeno por muito tempo e o tempo de inatividade não seja uma grande preocupação, a implantação de servidor único apresenta alguns riscos. A implantação de vários servidores é quase arbitrariamente escalável – pontos únicos de falha podem ser projetados e o desempenho pode ser o que você escolher, com a capacidade de adicionar capacidade rapidamente.

Dica 3 – Mude seu servidor web para NGINX

Nos primórdios da Web, o nome “Apache” era sinônimo de “servidor web”. Mas o NGINX foi desenvolvido no início dos anos 2000 e vem ganhando popularidade de forma constante; ele já é o servidor web número 1 entre 1.000, 10.000, 100.000 e [ngx_snippet name='proportion-top-sites'] no mundo.

O NGINX foi desenvolvido para resolver o problema C10K – ou seja, lidar com mais de 10.000 conexões simultâneas dentro de um determinado orçamento de memória. Outros servidores web precisam de um pedaço de memória para cada conexão, então eles ficam sem memória física e ficam lentos ou travam quando milhares de usuários querem acessar um site ao mesmo tempo. O NGINX lida com cada solicitação separadamente e pode ser dimensionado facilmente para muito mais usuários. (Também é excelente para propósitos adicionais, como descreveremos abaixo.)

Uma visão geral de alto nível da arquitetura do NGINX é mostrada abaixo.

Arquitetura para orientação de configuração Python usando capacidades NGINX em serviços web, balanceamento de carga e cache
Arquitetura NGINX, de The Architecture of Open Source Applications, Volume II

No diagrama, um servidor de aplicação Python se encaixa no bloco Application server no backend e é mostrado sendo acessado pelo FastCGI. O NGINX não “sabe” como executar Python, então ele precisa de um gateway para um ambiente que o faça. FastCGI é uma interface amplamente utilizada para PHP, Python e outras linguagens.

Entretanto, uma escolha mais popular para comunicação entre Python e NGINX é a Web Server Gateway Interface (WSGI). O WSGI funciona em ambientes multithread e multiprocessos, por isso ele é bem escalável em todas as opções de implantação mencionadas nesta postagem do blog.

Se você migrar para o NGINX como seu servidor web, há muito suporte disponível para as etapas envolvidas:

Este snippet mostra como você pode configurar o NGINX para uso com uWSGI – neste caso, um projeto usando o framework Python Django:

http { # ...
upstream django {
servidor 127.0.0.1:29000;
}

servidor {
ouvir 80;
nome_do_servidor meuapp.exemplo.com;

raiz /var/www/meuapp/html;

localização / {
índice index.html;
}

localização /estático/ {
alias /var/django/projetos/meuapp/estático/;
}

localização /principal {
incluir /etc/nginx/uwsgi_params;
uwsgi_pass django;

uwsgi_param Host $host;
uwsgi_param X-Real-IP $remote_addr;
uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto;
}
}
}

Dica 4 – Implemente o cache de arquivos estáticos

O armazenamento em cache de conteúdo estático envolve manter uma cópia de arquivos que não mudam com tanta frequência – o que pode significar a cada poucas horas ou nunca – em um local diferente do servidor de aplicativos. Um exemplo típico de conteúdo estático é uma imagem JPEG exibida como parte de uma página da web.

O cache de arquivos estáticos é uma maneira comum de melhorar o desempenho do aplicativo e, na verdade, acontece em vários níveis:

  • No navegador do usuário
  • Em provedores de Internet em vários níveis – desde a rede interna de uma empresa até um Provedor de Serviços de Internet (ISP)
  • Em um servidor web, como descreveremos aqui

A implementação de cache de arquivos estáticos no servidor web tem dois benefícios:

  • Entrega mais rápida ao usuário – O NGINX é otimizado para cache de arquivos estáticos e executa solicitações de conteúdo estático muito mais rápido do que um servidor de aplicativos.
  • Carga reduzida no servidor de aplicativos – O servidor de aplicativos nem mesmo vê solicitações de arquivos estáticos armazenados em cache, porque o servidor web as satisfaz.

O cache de arquivos estáticos funciona bem com uma implementação de servidor único, mas o hardware subjacente ainda é compartilhado pelo servidor web e pelo servidor de aplicativos. Se o servidor web tiver o hardware ocupado recuperando um arquivo em cache – mesmo que de forma muito eficiente – esses recursos de hardware não estarão disponíveis para o aplicativo, possivelmente deixando-o lento até certo ponto.

Para oferecer suporte ao cache do navegador, defina os cabeçalhos HTTP corretamente para arquivos estáticos. Considere o cabeçalho HTTP Cache-Control (e sua configuração max-age em particular), o cabeçalho Expires e as tags Entity . Para uma boa introdução ao tópico, consulte Usando NGINX e NGINX Plus como um Application Gateway com uWSGI e Django no Guia de administração do NGINX Plus.

O código a seguir configura o NGINX para armazenar em cache arquivos estáticos, incluindo arquivos JPEG, GIFs, PNG, arquivos de vídeo MP4, arquivos do PowerPoint e muitos outros. Substitua www.example.com pelo URL do seu servidor web.

server { # substitua a URL do seu servidor web por "www.example.com"
server_name www.example.com;
root /var/www/example.com/htdocs;
index index.php;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
# substitua o soquete, ou endereço e porta, do seu servidor Python
fastcgi_pass unix:/var/run/php5-fpm.sock;
# fastcgi_pass 127.0.0.1:9000;
} 

localização ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expira máx;
log_not_found desativado;
access_log desativado;
}
}

Dica 5 – Implemente Microcaching

O microcaching explora uma grande oportunidade para melhorar o desempenho em servidores de aplicativos que executam Python, PHP e outras linguagens. Para fins de cache, existem três tipos de páginas da web:

  • Arquivos estáticos – Eles podem ser armazenados em cache, conforme descrito na Dica 4 .
  • Páginas geradas por aplicativos e não personalizadas – Normalmente não faz sentido armazená-las em cache, pois elas precisam ser atualizadas. Um exemplo é uma página entregue a um usuário de comércio eletrônico que não está logado (veja o próximo ponto) – os produtos disponíveis, produtos similares recomendados e assim por diante podem estar mudando constantemente, por isso é importante fornecer uma página atualizada. No entanto, se outro usuário aparecer, digamos um décimo de segundo depois, pode ser aceitável mostrar a ele a mesma página que o usuário anterior.
  • Páginas personalizadas geradas por aplicativos – Não é possível armazená-las em cache, pois são específicas do usuário, e é improvável que o mesmo usuário veja a mesma página personalizada duas vezes. Um exemplo é uma página de comércio eletrônico para um usuário conectado; a mesma página não pode ser mostrada para outros usuários.
Microcache com NGINX
Arquivos estáticos e arquivos gerados por aplicativos não personalizados podem ser armazenados em cache

O microcaching é útil para o segundo tipo de página descrito acima – páginas geradas por aplicativos e não personalizadas. “Micro” refere-se a um breve período de tempo. Quando seu site gera a mesma página várias vezes por segundo, talvez não prejudique muito a atualização da página se você armazená-la em cache por um segundo. No entanto, esse breve período de armazenamento em cache pode descarregar bastante o servidor de aplicativos, especialmente durante picos de tráfego. Em vez de gerar 10, 20 ou 100 páginas (com o mesmo conteúdo) durante o período de tempo limite do cache, ele gera uma determinada página apenas uma vez, depois a página é armazenada em cache e exibida para muitos usuários do cache.

O efeito é meio milagroso. Um servidor que é lento ao lidar com dezenas de solicitações por segundo se torna bastante rápido ao lidar com exatamente uma. (Além, é claro, de quaisquer páginas personalizadas.) Nosso próprio Owen Garrett tem uma postagem de blog que detalha os benefícios do microcaching , com código de configuração. A principal mudança, configurar um cache proxy com tempo limite de um segundo, requer apenas algumas linhas de código de configuração.

proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inativo=600s max_size=100m;servidor {
proxy_cache cache;
proxy_cache_valid 200 1s;
# ...
}

Para mais exemplos de configuração, consulte o blog de Tyler Hicks‑Wright sobre Python e uWSGI com NGINX .

Conclusão

Na Parte I, abordamos soluções para aumentar o desempenho de uma implementação Python de servidor único, bem como o cache, que pode ser implantado em uma implementação de servidor único ou pode ser executado em um servidor proxy reverso ou em um servidor de cache separado. (O cache funciona melhor em um servidor separado.) A próxima parte, Parte 2 , descreve soluções de desempenho que exigem dois ou mais servidores.

Se você quiser explorar os recursos avançados do NGINX Plus para seu aplicativo, como suporte, monitoramento de atividades ao vivo e reconfiguração instantânea, comece hoje mesmo seu teste gratuito de 30 dias ou entre em contato conosco para discutir seus casos de uso .


"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."