O que fica à frente de quase todo serviço web
Bem-vindo
Se você digitar example.com em um navegador, quase nunca alcançará a máquina que realmente executa a aplicação. Você alcançará uma máquina que encaminha a solicitação para aquela que a executa. Essa máquina de encaminhamento tem um nome: um proxy reverso.
Esta lição ensina o que um proxy reverso faz, por que quase todo serviço web público se esconde atrás de um e quais são as três funções que a camada de borda executa simultaneamente.
Ao final, você entenderá:
- A diferença entre um cliente, um proxy e uma origem
- Por que um proxy à frente de uma origem protege, escala e permite trocar componentes sem que ninguém perceba
- As três funções que um proxy reverso executa simultaneamente: ocultar a origem, encerrar o TLS e distribuir a carga entre réplicas
- Como uma requisição viaja do navegador para o proxy, para o upstream e de volta, salto a salto
Ao final, você será capaz de raciocinar com confiança sobre o posicionamento de proxies, a separação de preocupações na borda e por que uma camada de proxy sem estado se multiplica de forma barata, enquanto uma única origem não.
Proxy Direto vs Proxy Reverso
Dois Direcionamentos de Proxy
Ambos os tipos de proxy ficam entre duas partes e retransmitem o tráfego. Eles diferem em qual parte eles representam.
Proxy de encaminhamento (forward proxy): fica à frente de um grupo de clientes. Os clientes conhecem o proxy; um servidor externo vê o endereço do proxy, não o endereço do cliente. Proxies de saída corporativos, filtros de conteúdo e proxies SOCKS se encaixam nesse padrão.
Proxy reverso (reverse proxy): fica à frente de um grupo de servidores. O mundo externo (clientes) se comunica com um endereço de proxy; os clientes não têm ideia de que um servidor real está escondido atrás dele. Quase todo serviço web público usa um.
Mnemônico: um proxy de encaminhamento oculta os clientes dos servidores. Um proxy reverso oculta os servidores dos clientes.
Por que se importar com a direção? A função, os modos de falha e o limite de segurança são diferentes. Um proxy de encaminhamento se preocupa com quem seus usuários contatam; um proxy reverso se preocupa com quem contata seus servidores.
Um cliente que envia tráfego através de ambos os tipos ao mesmo tempo percorre: client -> forward_proxy -> internet -> reverse_proxy -> origin.
Por Que Tanto Vive na Borda
A Camada de Borda Justifica Seu Custo
Um proxy reverso desempenha três funções ao mesmo tempo. Qualquer uma delas justifica a camada; desempenhar as três no mesmo endereço explica por que quase toda arquitetura web de produção tem a mesma forma na frente.
Função 1: Ocultar a origem. O proxy responde em um IP público. Os backends ficam em IPs privados aos quais a internet não pode acessar. Um atacante que deseja atingir a origem deve primeiro comprometer o proxy.
Função 2: Terminar TLS. O proxy detém o certificado para example.com e descriptografa as requisições HTTPS recebidas. Os backends se comunicam com o proxy via HTTP puro (ou TLS interno mais simples) através de um segmento de rede confiável. A rotação, renovação e política de cifras dos certificados ficam centralizadas em um único lugar.
Função 3: Distribuir carga. O proxy escolhe qual backend processará cada requisição. Os backends atrás de um mesmo proxy formam um pool; o proxy seleciona um por requisição usando uma estratégia (round-robin, menos conexões, hash em um cabeçalho). Adicionar capacidade significa adicionar um backend ao pool, em vez de informar a cada cliente um novo endereço.
Cada função é um pequeno programa. Juntas, elas explicam por que uma camada tão simples quanto "Caddy à frente de um aplicativo Python" carrega mais peso de design do que o próprio aplicativo Python.
Projetando para as Três Funções
Sua equipe executa uma pequena API em um único processo Python ouvindo na porta 8000 em uma única VM. O tráfego cresceu o suficiente para que uma única VM não consiga dar conta, e uma revisão de segurança apontou que a VM possui um IP público e executa seu próprio certificado TLS.
Você decide colocar um proxy reverso à frente. Esboce o layout: para onde o DNS aponta, onde fica o certificado, como a carga chega aos backends e o que muda na VM original?
Trocar um Componento Sem Ninguém Perceber
Indireção Compra Liberdade
Um ditado antigo da ciência da computação afirma: todo problema pode ser resolvido adicionando uma camada de indireção (exceto o problema de ter muitas camadas de indireção). O proxy reverso é uma das indireções mais úteis em sistemas distribuídos.
O que isso te proporciona:
- Backends substituíveis. Mover a aplicação de Python para Go? Migrar de um datacenter para outro? Lançar uma nova versão com zero downtime? Cada um desses cenários acontece atrás de um endereço público estável. Nada muda para os usuários.
- Escala independente. A camada de proxy escala com base em largura de banda e CPU na camada TLS. A camada de backend escala com base no trabalho da aplicação. Cada uma cresce em seu próprio eixo, pois vivem em máquinas diferentes.
- Contenção de falhas. Um deploy ruim no backend não derruba o endereço público. O proxy permanece ativo; você aplica uma correção ou faz rollback; o mundo se reconecta quando o backend se recupera.
- Preocupações transversais em um só lugar. Limitação de taxa (rate limiting), bloqueio geográfico, log de requisições, reescrita de cabeçalhos, cache, compressão de resposta: tudo isso vive no proxy. O código do backend permanece focado na aplicação.
Sem o proxy, cada um desses problemas deve viver dentro do processo da aplicação. Com o proxy, eles vivem em uma única camada que uma única equipe possui.
O custo: outra camada para operar. Equipes maduras aceitam esse custo porque a camada de proxy em si é sem estado (stateless) e escala horizontalmente; substituir um proxy por dois não requer coordenação.
Um Despliegue Azul/Verde Através do Proxy
Sua equipe executa a versão 1 da API em três VMs de backend (pool azul) atrás de um proxy reverso. Você deseja implantar a versão 2 com a capacidade de reverter em menos de trinta segundos, caso algo dê errado.
Você inicia três novas VMs de backend (pool verde) executando a versão 2, lado a lado com o pool azul, mas ainda não direciona nenhum tráfego para elas.
Do Navegador ao Backend e de Volta
Acompanhe um Pedido de Ponta a Ponta
Rastreie um único GET HTTPS de https://api.example.com/users/42 através de um proxy reverso à frente de um pool de backends.
Salto 1: resolução DNS. O navegador pergunta a um resolver por api.example.com. O resolver retorna o IP público do proxy (digamos, 203.0.113.10). O navegador abre uma conexão TCP para 203.0.113.10:443.
Salto 2: handshake TLS. O proxy apresenta seu certificado para api.example.com. O navegador valida o certificado, as duas partes concordam com uma chave de sessão e o canal criptografado é aberto.
Salto 3: pedido HTTP dentro do TLS. O navegador envia GET /users/42 HTTP/1.1\nHost: api.example.com\n.... O proxy descriptograia os bytes do pedido.
Salto 4: Seleção do backend. O proxy consulta seu pool de upstreams para api.example.com e escolhe um backend (por exemplo, 10.0.0.21:8000) usando sua estratégia de balanceamento de carga.
Salto 5: Requisição upstream. O proxy abre (ou reutiliza) uma conexão HTTP simples com 10.0.0.21:8000 e encaminha a requisição. O proxy pode reescrever cabeçalhos ao longo do caminho: adicionar X-Forwarded-For: <client-ip>, definir o Host: corretamente e remover cabeçalhos hop-by-hop, como Connection.
Salto 6: Processamento do backend. O aplicativo de backend lê a requisição, consulta seu banco de dados e constrói uma resposta JSON.
Salto 7: Resposta upstream. O backend envia a resposta de volta para o proxy como HTTP simples.
Salto 8: Resposta na borda. O proxy pode reescrever ou comprimir a resposta, criptografá-la novamente através da sessão TLS e enviá-la para o navegador.
Salto 9: Ciclo de vida da conexão. A sessão TLS geralmente permanece aberta para a próxima requisição (o HTTP/2 multiplexa muitas requisições em uma única conexão). A conexão do proxy para o backend frequentemente é mantida em pool para reutilização.
Todo serviço web público segue alguma variante desta estrutura. Conhecer os saltos permite raciocinar sobre onde a latência se acumula, onde o log deve pertencer e onde uma falha pode se esconder.
Para onde foi o tempo?
Um usuário reclama que a API parece lenta. Você mede e descobre que a requisição leva 850 ms de ponta a ponta. Os logs do servidor no backend mostram que a aplicação processou a requisição em 40 ms. Os logs do proxy mostram que o proxy gastou 50 ms na sua parte do trabalho (handshake TLS + roteamento + escrita da resposta).
Projete uma Borda Mínima para um Novo Serviço
Síntese
Você aprendeu a diferença entre um proxy direcional e um proxy reverso, os três trabalhos que um proxy reverso executa simultaneamente, por que ocultar a origem traz dividendos sempre que você precisa mudar algo e como uma solicitação flua salto a salto através da borda.
Agora aplique isso.
Uma pequena equipe planeja lançar um novo serviço chamado notes.example.com. Os usuários lerão e escreverão notas pessoais. A equipe executará duas VMs de backend no lançamento e espera escalar para dez no próximo ano. Eles querem HTTPS para os usuários, implantação gradual para novas versões e nenhuma exposição pública dos IPs dos backends.
Para Onde Este Curso Vai a Seguir
Para Onde Este Curso Vai a Seguir
Esta lição estabeleceu a forma da camada de borda. Mais quatro lições neste curso se baseiam nela:
- Escala Horizontal Sem Estado: por que uma camada de proxy (e os backends por trás dela) se multiplica de forma barata, e a matemática para dimensionar o número de réplicas sob picos de tráfego.
- Separação de Ingresso / Egresso: por que uma única caixa de proxy que trata tanto o tráfego de entrada quanto o de saída eventualmente falha de maneiras surpreendentes, e como dividir as camadas.
- Modos de Falha & Alcance do Impacto: como uma única mudança de configuração pode se propagar para uma interrupção total, e como redigir itens de ação sem culpa que previnam a recorrência.
- Observabilidade & Capacidade: o que medir na borda para descobrir que algo está quebrado antes que os usuários percebam.
Cada lição é independente. Juntas, elas fornecem um modelo mental funcional de uma frota em escala web.
Lição complementar: geometry_of_proxies_and_origins reformula tudo nesta lição como um grafo direcionado e explora o que a teoria dos grafos nos diz sobre um caminho de requisição.
Muito bem. Em frente.