Introdução
Nginx é um servidor web de alto desempenho que também é usado como proxy reverso, proxy de e-mail, balanceador de carga e cache HTTP. O Nginx é gratuito e de código aberto, permitindo que qualquer pessoa o baixe e use em seu ambiente de servidor.
Você já deve ter usado o Nginx para servir sites. Neste tutorial, discutiremos os outros recursos do Nginx. A capacidade de proxying HTTP do Nginx permite que ele passe requisições para servidores HTTP de backend para processamento. Com esse recurso, você pode configurar múltiplos servidores de backend. Ele permite que você dimensione sua infraestrutura conforme necessário para lidar com picos de requisições de clientes.
À medida que avançamos no tutorial, você aprenderá sobre como dimensionar sua infraestrutura usando as propriedades de balanceamento de carga do Nginx, buffering, e caching de respostas para melhorar o desempenho do seu servidor, além de garantir uma melhor experiência para os clientes. Vamos começar!
Antes de mais nada, para começar a usar o Nginx, dê uma olhada no nosso tutorial sobre como instalar o Nginx no seu servidor Ubuntu.
Informações Gerais sobre Proxying
Se o seu conhecimento sobre servidores web se resume a processar requisições de sites e servir páginas web, você pode estar se perguntando por que precisamos fazer o proxy de requisições. Abaixo, explicaremos os motivos por trás disso.
Um dos motivos para fazer o proxy de requisições do Nginx para outros servidores é apoiar a escalabilidade da sua infraestrutura. O Nginx, por padrão, lida com muitas conexões simultaneamente. Isso o torna perfeito para ser o primeiro ponto de contato para os clientes. E então ele pode passar as requisições para vários servidores de backend para lidar com o processamento real das requisições dos clientes. É isso que distribui a carga. Portanto, garante que você possa dimensionar sua infraestrutura o máximo possível. Também permite que você desative outros servidores para manutenção enquanto outros continuam a atender às requisições.
O segundo motivo pelo qual você pode querer fazer o proxy de requisições para outros servidores é quando está usando servidores de aplicação que não são adequados para lidar com requisições diretamente dos clientes em ambientes de produção reais. Vários frameworks, incluindo servidores web, não são adequados para alto desempenho como o Nginx. Permitir que o Nginx seja o ponto de entrada e faça o proxy das requisições para esses servidores de baixo desempenho pode garantir que seus usuários tenham uma experiência melhor. Além disso, pode garantir maior segurança para sua aplicação.
O processo de proxying de requisições no Nginx envolve manipular uma requisição do servidor Nginx e passá-la para outros servidores de backend para o processamento real. Assim que os outros servidores de backend processam a requisição, eles passam o resultado de volta para o Nginx. Ele então envia o resultado como uma resposta para o cliente. O cliente, neste caso, é um navegador web ou até mesmo um aplicativo web móvel. Os outros servidores de backend podem ser servidores locais que não estão acessíveis publicamente na internet, servidores remotos ou até mesmo outros servidores virtuais dentro das configurações de blocos de servidor do Nginx. Esses outros servidores para os quais o Nginx está fazendo o proxy de requisições são chamados de servidores upstream.
O Nginx pode fazer o proxy de requisições para servidores que se comunicam usando vários protocolos, incluindo HTTP(S), Memcached, SCGI, FastCGI, e uWSGI. Para cada tipo de protocolo, existem conjuntos de diretivas. Nosso foco para este tutorial é o protocolo HTTP. O Nginx analisa as requisições e os componentes de mensagem em um formato que o servidor upstream possa interpretar e processar.
Analisando um Proxy Pass HTTP Básico
O tipo mais simples de proxy envolve passar uma requisição para um único servidor que se comunica via HTTP. Esse tipo de proxy geralmente é conhecido como “proxy pass” e é tratado pela diretiva apropriadamente chamada proxy_pass dentro dos arquivos de configuração do Nginx.
A diretiva proxy_pass aparece dentro de blocos location. Ela também está dentro de blocos de um contexto de localização e em contextos limit_except. Quando uma requisição corresponde a um local com uma diretiva proxy_pass dentro, a requisição vai para a URL que a diretiva especifica. Abaixo está um exemplo de um trecho de configuração:
|
1 2 3 4 |
listen 80; location / { proxy_pass http://127.0.0.1:3000; } |

No exemplo acima, as requisições para a porta 80 iriam para localhost:3000:

A captura de tela acima mostra a página padrão do Nginx quando você tenta acessar o localhost. Após reiniciar o servidor Nginx com a diretiva proxy pass em vigor, todas as requisições irão para a porta 3000. Uma aplicação de demonstração está rodando na porta 3000, o que você pode ver na imagem abaixo, e você pode acessá-la diretamente do localhost sem especificar a porta:

No próximo exemplo, nenhuma URI foi especificada no final do servidor na definição proxy_pass. Para definições que se encaixam nesse padrão, a URI que o cliente requisita será passada para o servidor upstream como está.
|
1 2 3 |
location /corresponder/url/aqui { proxy_pass http://example.com; } |
Por exemplo, quando este bloco trata uma requisição para /match/url/here, a URI da requisição irá para o servidor example.com como http://example.com/match/url/here.
Abaixo está um exemplo de um trecho de configuração alternativo:
|
1 2 3 |
location /corresponder/url/aqui { proxy_pass http://example.com/new/url/prefix; } |
Como você pode ver no trecho acima, definimos um segmento de URI no final do servidor proxy como new/url/prefix. Quando você define uma URI na definição proxy_pass, a parte da requisição que corresponde à definição de location é substituída por esta URI ao ser enviada para o servidor upstream para processamento.
Por exemplo, uma requisição para /match/url/here no servidor Nginx passa para o servidor upstream como http://example.com/new/url/here. O /match/url é substituído por /new/url. Tenha este ponto em mente.
Em alguns casos, a passagem de URIs como acima não é possível. Nesses casos, o Nginx ignora a URI no final da definição proxy_pass. Em última análise, ou a URI original do cliente ou a URI modificada por outras diretivas é passada para o servidor upstream.
Um exemplo é quando expressões regulares correspondem ao location. O Nginx pode não ser capaz de determinar qual parte da URI correspondeu à expressão. Portanto, ele envia a URI de requisição original do cliente. Isso causa a reescrita e o tratamento da URI do cliente no mesmo bloco. Nesse caso, a URI reescrita é passada.
Como o Nginx Processa Cabeçalhos?
Os cabeçalhos são cruciais para a forma como um servidor processa uma requisição. Alguns cabeçalhos podem incluir informações de autenticação. Portanto, devemos entender como o proxy do Nginx processará os cabeçalhos. A requisição de proxy do Nginx para o servidor upstream parecerá diferente daquela que veio diretamente do cliente. Algumas das diferenças são resultado dos cabeçalhos que acompanham a requisição de proxy.
Durante o encaminhamento por proxy de uma requisição, o Nginx fará ajustes nos cabeçalhos de requisição que recebe do cliente. Alguns desses ajustes incluem:
-
Eliminar todos os cabeçalhos vazios. Cabeçalhos vazios apenas sobrecarregam a requisição, então não há sentido em passá-los para o servidor upstream.
-
Quaisquer cabeçalhos contendo sublinhados são considerados inválidos por padrão e, portanto, são removidos da requisição. Se você quiser alterar esse comportamento e permitir que o Nginx interprete cabeçalhos com sublinhados como válidos, poderá definir a diretiva underscores_in_headers como “on”. Se não o fizer, esses cabeçalhos do cliente nunca chegarão ao servidor upstream.
-
O cabeçalho “Host” é reescrito para o valor especificado pela variável $proxy_host. Este é o endereço IP ou nome e número de porta do servidor upstream, conforme especificado pela diretiva proxy_pass.
-
O valor do cabeçalho “Connection” muda para “close”. O cabeçalho de conexão contém informações sobre uma conexão específica estabelecida entre duas partes. Quando o Nginx define seu valor como close, ele indica ao servidor upstream que a conexão será fechada assim que a requisição original for respondida, portanto, ele não deve esperar que seja uma conexão persistente.
Aqui estão alguns pontos que podemos observar a partir dos ajustes nos cabeçalhos de requisição de proxy descritos acima:
-
Se você não deseja que um cabeçalho seja passado para o servidor upstream, defini-lo como uma string vazia irá removê-lo completamente da requisição.
-
Se a aplicação no seu servidor upstream for processar cabeçalhos não padrão, certifique-se de que os cabeçalhos não tenham um sublinhado. Opcionalmente, você pode definir a diretiva underscores_in_headers como “on” na sua configuração (válida tanto no contexto da declaração padrão do servidor para a combinação de endereço IP/porta quanto no contexto HTTP). Fazer isso garantirá que os cabeçalhos não sejam marcados como inválidos e, portanto, sejam realmente passados para o servidor upstream.
-
O cabeçalho “Host” é bastante importante na maioria das situações de proxy. Por padrão, ele é definido com o valor de $proxy_host, uma variável que contém o nome de domínio ou endereço IP e porta recuperados da especificação proxy_pass. Este endereço é selecionado por padrão e extraído diretamente das informações de conexão. É o único endereço para o qual o Nginx tem a garantia de que o servidor upstream responderá.
Abaixo estão os valores mais comuns para o cabeçalho “Host”:
-
$host – uma variável definida por ordem de preferência para o hostname da própria linha de requisição, o cabeçalho “Host” da requisição do cliente ou o nome do servidor correspondente à requisição.
-
$http_host – uma variável que define o cabeçalho “Host” para o cabeçalho “Host” da requisição do cliente. Os cabeçalhos na requisição do cliente estão sempre disponíveis para o Nginx como variáveis. Essas variáveis começam com o prefixo $http_, seguido pelo nome do cabeçalho em letras minúsculas. Embora a variável $http_host funcione bem na maioria das vezes, quando a requisição do cliente carece de um cabeçalho “Host” válido, isso pode resultar em falha no encaminhamento.
-
$proxy_host – uma variável que define o cabeçalho “Host” para a combinação de nome de domínio ou endereço IP e porta recuperada da especificação do proxy_pass. Este é o comportamento padrão, do ponto de vista do Nginx, e por isso é considerado seguro. No entanto, pode não ser o que o servidor precisa para processar a requisição corretamente.
A maioria das configurações envolverá a definição do cabeçalho “Host” para a variável $host. É altamente flexível e fornecerá cabeçalhos preenchidos com precisão para o servidor upstream.
Definindo e Modificando Cabeçalhos
A diretiva proxy_set_header nos permite definir ou modificar cabeçalhos para conexões de proxy. No cabeçalho “Host” discutido anteriormente, podemos fazer o seguinte para modificar e adicionar cabeçalhos adicionais comuns com requisições em proxy:
|
1 2 3 4 5 6 7 8 |
location /match/here { proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $schema; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://example.com/new/prefix; } |
No trecho de configuração acima, definimos o cabeçalho “Host” para a variável $host que contém informações sobre o host original que está sendo requisitado. Definimos o cabeçalho X-Forwarded-Proto com informações sobre o esquema da requisição original do cliente (pode ser uma requisição HTTP ou HTTPS).
Passamos o endereço IP real do cliente para o X-Real-IP. Isso permite que o servidor upstream tome decisões apropriadas ou armazene logs com base na origem do IP do cliente. O cabeçalho X-Forwarded-For contém uma lista de todos os endereços IP pertencentes aos servidores pelos quais o cliente passou por proxy antes de chegar a este ponto. No trecho de código acima, nós o definimos para a variável $proxy_add_x_forwarded_for. Esta variável assumirá o valor do cabeçalho X-Forwarded-For original obtido do cliente e adicionará o endereço IP do servidor proxy Nginx ao final.
Se você deseja que as diretivas proxy_set_header sejam referenciadas em mais de um local, você pode movê-las para o contexto server ou http. Considere o trecho de configuração abaixo:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location /correspondência/aqui { proxy_pass http://example.com/new/prefix; } location /diferente/correspondência { proxy_pass http://example.com; } |
Definindo um Contexto Upstream para Balanceamento de Carga de Conexões com Proxy
Até este ponto, você compreende como fazer um proxy http simples para um único servidor upstream de backend. Felizmente, com o Nginx, você pode dimensionar essa configuração definindo pools de servidores de backend para os quais passar as solicitações para processamento.
O Nginx fornece uma diretiva chamada upstream que é usada para definir um pool de servidores. Na configuração da diretiva, você deve apenas especificar servidores que sejam capazes de lidar com a solicitação de um cliente. O Nginx como um servidor proxy permite o dimensionamento da infraestrutura com o mínimo de esforço. A diretiva upstream deve ser especificada dentro do contexto http da sua configuração do Nginx.
Aqui está um exemplo mostrando a diretiva upstream:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
upstream several_backend_hosts { server host1.example.com; server host2.example.com; server host3.example.com; } server { listen 80; server_name example.com; location /proxy-me { proxy_pass http://several_backend_hosts; } } |
No trecho de código de configuração acima, definimos um contexto upstream chamado several_backend_hosts. O nome do contexto definido agora está disponível dentro dos proxy passes. Ele pode ser usado como se fosse um domínio normal, conforme mostrado no exemplo. Dentro do bloco server, passamos todas as solicitações feitas para example.com/proxy-me/… para o pool que definimos usando a diretiva upstream, neste caso, several_backend_hosts. Um host é selecionado dentro do pool para lidar com as solicitações recebidas aplicando um algoritmo configurável. Por padrão, a seleção segue um round-robin (circular) – cada solicitação é roteada para um host diferente por sua vez.
Como Alterar o Algoritmo de Balanceamento do Upstream
Como destacado acima, o processo de seleção segue um processo round-robin. Nesta seção, veremos como podemos modificar o algoritmo de balanceamento usado pelo pool upstream. Para modificar o algoritmo, você inclui outras diretivas ou flags dentro do contexto upstream, conforme definido abaixo:
-
(round-robin) – se nenhuma outra diretiva de balanceamento upstream for especificada, por padrão, cada servidor definido no contexto upstream receberá solicitações sequencialmente, por sua vez.
-
least_conn – esta diretiva instrui o upstream a selecionar o servidor backend com o menor número de conexões ativas. Isso é aplicável em situações em que as conexões com um servidor backend podem persistir por um tempo.
-
hash – esta diretiva é comum para o proxy do memcached. As conexões são passadas para os servidores backend com base no valor de uma chave hash fornecida aleatoriamente. O valor da chave hash pode ser composto por variáveis, texto ou uma combinação de ambos. O hash acaba sendo o único método de balanceamento que requer entrada dos usuários para atuar como a chave a ser usada para o hash.
-
ip_hash – esta diretiva instrui o upstream a distribuir solicitações para diferentes servidores com base no endereço IP do cliente. Os três primeiros octetos do endereço IP são a chave para determinar qual servidor deve processar uma solicitação. Uma vantagem desta diretiva é que os clientes tendem a receber o mesmo servidor a cada vez, garantindo assim a consistência da sessão.
Aqui está um exemplo de como podemos adicionar a diretiva do algoritmo de balanceamento ao contexto upstream:
|
1 2 3 4 5 6 7 8 |
upstream several_backend_hosts { least_conn; server host1.example.com; server host2.example.com; server host3.example.com; } |
No trecho acima, o Nginx selecionará qualquer um dos servidores com menos conexões para processar uma solicitação de entrada. A diretiva ip_hash segue a mesma sintaxe. Para a diretiva hash, você deve fornecer uma chave de sua escolha para fazer o hash, aqui está um exemplo:
|
1 2 3 4 5 6 7 8 |
upstream several_backend_hosts { hash $remote_addr$remote_port consistent; server host1.example.com; server host2.example.com; server host3.example.com; } |
O hash usado aqui será o resultado do endereço IP e da porta do cliente. O parâmetro opcional consistent implementa o algoritmo de hash consistente Ketama. Isso garante um impacto mínimo no seu cache caso você altere seus servidores upstream.
Como especificar o peso do servidor para balanceamento
Por padrão, quando você declara servidores backend, cada servidor recebe o mesmo peso. A premissa é que cada servidor possui os recursos e capacidades para lidar com a mesma quantidade de carga, claro, isso levando em consideração qualquer algoritmo de balanceamento que você especificar no contexto upstream. Para alterar esse comportamento padrão, você pode definir um peso alternativo para cada servidor durante a declaração. Vamos considerar um exemplo:
|
1 2 3 4 5 |
upstream backend_hosts { server host1.example.com weight=2; server host2.example.com; server host3.example.com; } |
Neste exemplo, o host1.example.com receberá o dobro do tráfego dos outros dois servidores. O peso de cada servidor é um por padrão.
Liberando servidores backend com buffers
Ao configurar o proxy na configuração do seu servidor, você pode se preocupar com o impacto no desempenho ao adicionar mais servidores ao processo. Felizmente, o Nginx vem com recursos de buffer e cache que podem ajudar a mitigar esses problemas de desempenho.
A velocidade de duas conexões diferentes certamente afetará a experiência do cliente ao fazer proxy para outro servidor:
-
A primeira conexão é do cliente para o proxy Nginx.
-
A segunda conexão é do proxy Nginx para o servidor upstream de backend.
O Nginx pode ajustar seu comportamento para ajudar a otimizar qualquer uma das conexões conforme necessário.
Se removermos os buffers, os dados do backend upstream começam a ser transmitidos para o cliente imediatamente no proxy Nginx. Se você sabe que seus clientes são rápidos, pode desativar completamente o buffering para garantir que os dados cheguem ao cliente rápido o suficiente. Quando você tem os buffers ativados, o proxy Nginx armazena temporariamente os dados de resposta recebidos do servidor upstream de backend. Em seguida, ele envia os dados para o cliente dependendo de sua velocidade. Assim que o Nginx tiver a resposta em seus buffers, ele poderá fechar a conexão com o servidor backend. Ele então distribuirá os dados para o cliente em uma velocidade que o cliente suporte. Ao mesmo tempo, permite que o servidor backend continue processando outras solicitações de entrada.
Por padrão, o Nginx terá o buffering ativado. Isso ocorre porque não podemos saber as velocidades de conexão dos clientes. Os clientes tendem a ter conexões diferentes que podem ser mais lentas. Abaixo, definiremos as várias diretivas que podemos especificar para ajustar o comportamento de buffering do Nginx. As diretivas podem ser definidas nos contextos http, server ou location, no entanto, você deve observar que as diretivas de dimensionamento são configuradas por solicitação. Portanto, aumentá-las além do absolutamente necessário pode afetar o desempenho do seu servidor quando houver muitas solicitações de clientes recebidas. Aqui estão as diretivas:
-
proxy_buffering – a diretiva que controla se o buffering está ativo para um contexto específico e contextos filhos. A configuração padrão para proxy_buffering é “on”.
-
proxy_buffer_size – a diretiva que especifica o tamanho do buffer para armazenar cabeçalhos encontrados em uma resposta de um servidor backend. Os cabeçalhos constituem a primeira parte da resposta de um servidor backend. O buffering desses cabeçalhos é separado do restante da resposta. Por padrão, o tamanho definido para este buffer é o mesmo que o de proxy_buffers. No entanto, se as informações do cabeçalho forem pequenas, você pode definir o tamanho para um valor menor.
-
proxy_buffers – a diretiva que controla o número (primeiro argumento) e o tamanho (segundo argumento) dos buffers para respostas em proxy. A configuração padrão especifica 8 buffers de tamanho igual a uma página de memória (seja 4k ou 8k). Você pode permitir o buffering de mais informações aumentando o número de buffers.
-
proxy_max_temp_file_size – a diretiva que especifica o tamanho máximo, por requisição, para um arquivo temporário no disco. Arquivos temporários são criados quando a resposta do upstream é grande demais para caber em um buffer.
-
proxy_busy_buffers_size – a diretiva que especifica o tamanho máximo dos buffers que podem passar como “prontos para o cliente” e, portanto, ocupados. Um cliente só pode ler os dados de um buffer por vez. No entanto, os buffers ficam em uma fila para serem enviados ao cliente em lotes. Você pode especificar o tamanho do espaço de buffer permitido para ficar neste estado modificando esta diretiva.
-
proxy_temp_file_write_size – a diretiva que especifica a quantidade de dados que o Nginx gravará no arquivo temporário de uma só vez quando a resposta do servidor backend upstream for grande demais para caber nos buffers configurados.
-
proxy_temp_path – a diretiva que especifica o caminho para o local no disco onde o Nginx deve armazenar quaisquer arquivos temporários quando a resposta do servidor backend upstream for grande demais para caber nos buffers configurados.
O Nginx é altamente customizável, fornecendo várias diretivas para ajustar o comportamento do buffering. Na maioria dos casos, os valores padrão funcionarão perfeitamente. Ao mesmo tempo, é bom saber que você pode ajustar alguns desses valores para sua implementação personalizada. Na maioria das vezes, você desejará ajustar as diretivas proxy_buffers e proxy_buffer_size.
Abaixo está um exemplo que aumenta o número de buffers de proxy disponíveis para cada requisição upstream. Ele faz isso enquanto reduz o tamanho do buffer que armazena os cabeçalhos:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
server { proxy_buffering on; proxy_buffer_size 1k; proxy_buffers 24 4k; proxy_busy_buffers_size 8k; proxy_max_temp_file_size 2048m; proxy_temp_file_write_size 32k; location / { proxy_pass http://example.com; } } |
Vamos ver como você pode servir dados mais rapidamente para clientes rápidos desativando o buffering completamente. Se acontecer de o seu cliente não ser rápido o suficiente, o Nginx usará buffers automaticamente. No entanto, ele primeiro enviará os dados para o cliente em vez de esperar pelos pools de buffer. Essa configuração traz uma desvantagem. Ela faz com que a conexão com o servidor upstream permaneça aberta para clientes lentos até que o cliente tenha recebido todos os dados da resposta. Se o buffering estiver definido como “off”, apenas o buffer definido pela diretiva proxy_buffer_size será usado. Aqui está um trecho mostrando como você especificaria o buffering desativado:
|
1 2 3 4 5 6 7 8 9 |
server { proxy_buffering off; proxy_buffer_size 4k; location / { proxy_pass http://example.com; } } |
-
Configurando uma Infraestrutura de Alta Disponibilidade (HA) (Configuração opcional)
Você pode adicionar um conjunto redundante de balanceadores de carga à configuração do proxy Nginx, garantindo que ele seja mais robusto e, portanto, altamente disponível. Uma configuração de alta disponibilidade (HA) é uma infraestrutura sem ponto único de falha. Os balanceadores de carga fazem parte dessa configuração. Com mais de um balanceador de carga, você pode evitar possíveis inatividades se um balanceador de carga falhar ou ficar offline para manutenção.
Como implementar o cache de proxy do Nginx para reduzir os tempos de resposta
Na seção anterior, discutimos como usar o buffering para liberar os servidores de backend para lidar com mais requisições. O Nginx vem com outro recurso que nos permite armazenar em cache os dados de resposta do backend. Ele elimina completamente a necessidade de se conectar ao upstream para todas as requisições recebidas.
Implementando um cache de proxy
A diretiva proxy_cache_path nos permite configurar um cache especificando uma área no disco para usar no armazenamento de conteúdo em proxy. A diretiva proxy_cache_path é definida no contexto http.
O trecho de código de configuração abaixo é um exemplo de como você pode implementar um sistema de cache:
|
1 2 3 4 5 6 |
http { proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=backendcache:8m max_size=50m; proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args"; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; } |
Neste trecho de código, usamos a diretiva proxy_cache_path para definir um diretório no sistema de arquivos que conterá nosso cache. O /var/lib/nginx/cache é o diretório que definimos neste caso. Você é livre para definir o caminho de diretório de sua escolha. Use os seguintes comandos para criar os diretórios escolhidos, com as permissões e propriedade corretas:
|
1 2 3 |
sudo mkdir -p /var/lib/nginx/cache sudo chown www-data /var/lib/nginx/cache sudo chmod 700 /var/lib/nginx/cache |
No trecho de código, o parâmetro levels= especifica a organização do cache. O Nginx criará uma chave de cache fazendo o hash do valor de uma chave (especificada usando a diretiva proxy_cache_key). Os níveis que especificamos (1:2) indicam que um diretório de um único caractere (ou seja, o último caractere do valor em hash) com um subdiretório de dois caracteres (retirado dos próximos dois caracteres a partir do final do valor em hash) será criado. Na maioria dos casos, isso não será uma preocupação para você. No entanto, é bom saber como isso ajuda o Nginx a encontrar rapidamente os valores relevantes.
O parâmetro keys_zone= define o nome de uma zona de cache, que no nosso caso chamamos de backendcache. Aqui, também definimos quantos metadados queremos armazenar. Neste exemplo, estamos armazenando 8 MB de chaves. O Nginx pode armazenar cerca de 8000 entradas para cada megabyte. O parâmetro max_size especifica o tamanho máximo dos dados reais em cache, 50MB para o nosso exemplo.
Você também deve notar a diretiva proxy_cache_key usada. Esta diretiva especifica a chave que usaremos para armazenar os valores em cache. Usaremos a mesma chave para verificar se a requisição existe no cache. Especificamos que essa chave seja uma combinação do esquema (http ou https), do método de requisição HTTP e do host e URI requisitados.
Além disso, usamos a diretiva proxy_cache_valid. Esta diretiva pode ser especificada várias vezes para vários códigos de status. Ela nos permite especificar por quanto tempo armazenar os valores dependendo do código de status. No trecho de código, especificamos 10 minutos para códigos de sucesso e 1 minuto para respostas 404.
Como configuramos a zona de cache, o próximo passo é colocar a configuração em vigor, dizendo ao Nginx quando usar o cache. Abaixo está um trecho de configuração mostrando como podemos implementar o uso deste cache:
|
1 2 3 4 5 6 7 8 9 |
server { location /proxy-me { proxy_cache backendcache; proxy_cache_bypass $http_cache_control; add_header X-Proxy-Cache $upstream_cache_status; proxy_pass http://backend; } } |
Na diretiva proxy_cache, especificamos que a zona de cache backendcache deve ser usada para este contexto. Se você escolheu um nome diferente na configuração do cache, é aqui que você o substituirá. Para cada entrada válida, o Nginx verificará o cache antes de passar uma requisição para o servidor upstream de backend.
Definimos a diretiva proxy_cache_bypass para usar a variável $http_cache_control. Esta variável diz ao servidor se ele deve responder com uma resposta em cache ou com uma versão nova e não armazenada em cache do recurso. Configurar adequadamente esta diretiva permite que o Nginx lide corretamente com vários tipos de requisições recebidas dos clientes.
Um cabeçalho adicional chamado X-Proxy-Cache também é especificado. Este cabeçalho tem o valor da variável $upstream_cache_status. Ele nos fornece informações sobre se a requisição resultou em um cache hit, um cache miss ou se o cache foi explicitamente ignorado. Tais informações podem ser úteis para o cliente e cruciais durante a depuração de aplicações.
Pontos Importantes sobre o Armazenamento em Cache de Resultados
Embora o cache melhore muito o desempenho do seu servidor proxy, você deve observar o seguinte ao implementar o cache:
Quaisquer dados relacionados às informações pessoais de um usuário não devem ser armazenados em cache, para evitar cenários em que os dados de um usuário fiquem visíveis para outro usuário.
Seus servidores de backend devem dar conta de todos os elementos dinâmicos do seu site. Temos vários cabeçalhos Cache-Control que podemos especificar em nossa resposta para atender a diferentes propósitos. Vamos discuti-los:
-
no-cache – especifica que o proxy deve verificar se os dados foram alterados no backend antes de servir uma resposta. Isso é aplicável para dados dinâmicos e importantes. Um cabeçalho de metadados com hash ETag é verificado a cada requisição e, se o backend retornar o mesmo valor de hash, o valor anterior será servido.
-
no-store – especifica que nenhum dado recebido deve ser armazenado em cache, portanto, cada requisição irá ao servidor para obter dados novos. Este é o método mais seguro para dados confidenciais.
-
private – especifica que nenhum espaço de cache compartilhado deve armazenar os dados em cache. Você pode usar este cabeçalho para especificar o cache no navegador do usuário, mas também informar ao servidor proxy para considerar os dados inválidos para requisições subsequentes.
-
public – especifica uma resposta pública e permite o cache em qualquer ponto da conexão.
Você pode especificar por quanto tempo deseja que o cache dure em segundos usando o cabeçalho max-age. Os vários cabeçalhos definidos acima podem ajudar você a implementar o cache mantendo os dados confidenciais seguros, os dados dinâmicos atualizados e, o mais importante, melhorando o desempenho do seu servidor.
Se os seus servidores de backend estiverem executando servidores Nginx, você pode especificar dentro dos blocos de servidor por quanto tempo um cache deve ser válido. Você pode fazer isso adicionando a diretiva expires à configuração, conforme mostrado abaixo:
|
1 2 3 4 5 6 7 |
location / { expires 59m; } location /check-me { expires -1; } |
O primeiro bloco permite o cache de conteúdo por 59 minutos, enquanto o segundo bloco indica que não deve haver cache. Essas configurações se aplicam às opções de cabeçalhos Cache-Control, por exemplo, “no-cache” para o segundo bloco.
Você pode usar a diretiva add-header para definir valores adicionais:
|
1 2 3 4 |
location /private { expires -1; add_header Cache-Control "no-store"; } |
Conclusão
Neste tutorial, aprendemos sobre os recursos poderosos do Nginx. O Nginx é tanto um servidor web quanto, mais importante, um proxy reverso. O design do Nginx o torna capaz de lidar com milhares de conexões simultâneas. Isso o torna perfeito para balanceamento de carga. Devido ao seu design, o proxy de requisições para outros servidores de backend para processamento é bastante simples.
Com o conhecimento deste tutorial, você deve ser capaz de implementar proxies complexos e balanceadores de carga, graças à flexibilidade do Nginx.
Aqui estão alguns recursos que você pode encontrar no nosso blog que podem ajudar você a se familiarizar ainda mais com o Nginx:
Feliz computação!
Comentários
Nenhum comentário ainda. Seja o primeiro.