Abra elido.me/abc123 e algo tem de transformar essa cadeia curta num endereço web completo antes que o seu browser possa carregar qualquer coisa. O mecanismo é mais simples do que a maioria das pessoas supõe. Um encurtador de URL armazena um mapeamento de um código curto para um URL de destino longo. Quando clica no link curto, o serviço trata o código como uma chave de consulta, encontra o destino e devolve um redirecionamento HTTP que diz ao seu browser para onde ir realmente. Um pedido entra, um redirect sai.
Essa é toda a ideia. Todo o resto é engenharia em torno de três pressões: tornar a consulta rápida, manter os códigos curtos e únicos, e registar o clique sem atrasar ninguém. Esta publicação percorre como funcionam os encurtadores de URL do início ao fim, usando a arquitetura de borda da Elido como exemplo concreto enquanto mantém a explicação verdadeira para encurtadores em geral. Cobriremos o mapeamento slug-para-URL, como os códigos curtos são gerados, onde os dados ficam armazenados, a escolha do redirect 301-versus-302 que confunde mais pessoas do que qualquer outra coisa, como é que um redirecionamento HTTP realmente parece na rede, por que razão o caching na borda importa e como um clique é contado de forma assíncrona.
Como Funcionam os Encurtadores de URL: o Mapeamento no Centro#
Elimine a infraestrutura e um encurtador de URL é um armazém chave-valor com um handler de redirect acoplado. A chave é o slug, o código curto após o domínio. O valor é o destino, o URL longo que originalmente colou.
Quando cria um link curto, o encurtador escreve uma linha: este slug aponta para aquele destino. Quando alguém visita o link curto, o encurtador lê essa linha de volta e age sobre ela. Criar links é raro; lê-los é constante. Um único link de marketing pode ser escrito uma vez e depois lido centenas de milhares de vezes ao longo da sua vida. Esse rácio com muitas leituras é o facto mais importante sobre o fluxo de trabalho, e molda cada decisão de design que se segue, especialmente o caching.
O mapeamento em si pode conter mais do que um destino. Na Elido, um slug pode conter regras de segmentação, pelo que um link curto encaminha para diferentes destinos por país, dispositivo, idioma ou tempo. É o que chamamos de smart link, e é ainda a mesma consulta, apenas com uma pequena avaliação de regras após a leitura. A relação central nunca muda: slug entra, destino sai.
Gerar o Código Curto#
Se o slug é a chave, de onde vem? Há duas abordagens bem estabelecidas, e a maioria dos encurtadores usa uma ou uma mistura de ambas.
A primeira é a codificação base62 de um ID de base de dados. Cada novo link recebe um ID inteiro com incremento automático da base de dados. Esse inteiro é codificado em base62, que usa os 62 caracteres seguros para URL a-z, A-Z e 0-9. O ID 1 torna-se b, o ID 125 torna-se um código de dois caracteres, e assim por diante. Base62 é denso: três caracteres cobrem cerca de 238.000 links, cinco caracteres cobrem aproximadamente 916 milhões, seis cobrem cerca de 56 mil milhões. Os códigos ficam curtos e, porque mapeiam um-para-um para IDs únicos, nunca colidem. A desvantagem é que IDs sequenciais são adivinháveis, por isso muitos sistemas baralham ou deslocam o espaço de IDs antes de codificar.
A segunda abordagem é a geração aleatória. Escolha uma cadeia aleatória de comprimento fixo do mesmo alfabeto, depois verifique a base de dados para confirmar que ainda não foi tomada. Se colidir, gere outra. As colisões são extremamente raras em comprimentos sensatos, por isso o ciclo de nova tentativa quase nunca corre. Os slugs aleatórios não são enumeráveis, o que é o argumento de segurança a favor deles.
Os slugs personalizados, os com marca como elido.me/spring-sale, assentam sobre qualquer dos esquemas. O utilizador fornece a cadeia; o encurtador valida-a para caracteres permitidos e verifica a unicidade contra o mesmo índice antes de guardar. Quer o slug seja gerado ou escolhido manualmente, acaba no mesmo lugar: uma coluna única no armazém de dados.
Onde Ficam os Dados#
O mapeamento slug-para-destino precisa de um lar que possa responder "para onde aponta este slug" de forma rápida e consistente. Para a fonte de verdade, esse lar é quase sempre uma base de dados relacional. A Elido usa o Postgres, com o slug armazenado como uma coluna indexada única para que uma consulta seja uma leitura com chave única em vez de uma varredura de tabela. O Postgres mantém o registo canónico de cada link, utilizador e workspace.
Mas aceder ao Postgres em cada clique seria desperdiçador dado o rácio de muitas leituras. Uma consulta de slug com chave no Postgres normalmente corre em um a três milissegundos, o que soa rápido até multiplicar pelo volume de cliques de um link viral e lembrar que uma ligação de base de dados é um recurso finito. Por isso, os encurtadores de produção colocam uma cache à frente da base de dados. A cache é onde a maioria das leituras é efetivamente servida; a base de dados é o fallback para qualquer coisa que a cache ainda não tenha.
A Elido executa uma cache de dois níveis à frente do Postgres. O primeiro nível é uma cache LRU em processo que vive dentro do próprio binário de redirect, que devolve um destino em algumas centenas de nanossegundos sem qualquer salto de rede. O segundo nível é um cluster Redis na mesma região, que serve em menos de um milissegundo. Apenas um miss a frio - um slug que nenhum dos níveis viu recentemente - cai para uma chamada gRPC de origem contra api-core, que lê o Postgres. A taxa de acertos combinada em ambos os níveis de cache fica em torno de 99,4%, por isso a base de dados é consultada em aproximadamente um pedido em 167. A análise completa de como essa cache se comporta, incluindo a sua política de evicção e os modos de falha que encontrámos, está no nosso artigo sobre estratégia de cache.
O Que É Realmente um Redirecionamento HTTP#
Uma vez que o encurtador tem o destino, tem de o devolver ao browser. Faz isso com um redirecionamento HTTP, que é apenas um tipo específico de resposta. Em vez de devolver conteúdo de página com um 200 OK, o servidor devolve um código de estado 3xx e um cabeçalho Location que nomeia o URL real. Na rede, a resposta é pequena:
HTTP/1.1 302 Found
Location: https://shop.example.com/spring-collection
Content-Length: 0
O browser lê o código de estado, vê um cabeçalho Location e imediatamente emite um novo pedido para esse endereço. Para a pessoa que clica, parece uma única navegação; por baixo são dois pedidos, com o link curto a agir como uma consulta de diretório rápida no meio. A semântica de cada código 3xx está definida no RFC 7231, e o guia da Mozilla sobre redirecionamentos HTTP é a referência prática mais clara sobre o que cada código faz.
O corpo está vazio porque não há nada a renderizar. O payload completo é a linha de estado e o cabeçalho. É por isso que os redirects são baratos de servir: não há template, não há join de base de dados para conteúdo, não há markup. Resolver o slug, definir um cabeçalho, enviar.
301 vs 302: a Escolha que Define a Sua Análise#
Aqui é onde os encurtadores tomam silenciosamente uma decisão que a maioria dos utilizadores nunca vê, mas que determina se o seu link é editável e rastreável. O código de estado do redirect não é uma formalidade. As duas opções comuns comportam-se de forma muito diferente.
Um 301 Moved Permanently diz ao browser, e a cada proxy e CDN entre si e o servidor, que este link curto apontará sempre para o mesmo lugar. Por isso, guardam-no em cache. Um 301 é guardado agressivamente. Da próxima vez que o visitante clicar nesse link curto, o browser pode resolvê-lo a partir da cache sem nunca contactar o encurtador. Isso é ótimo para evitar uma viagem de rede, e é um desastre para uma ferramenta de links, porque duas coisas quebram. Primeiro, a análise fica cega: cliques servidos a partir da cache do browser nunca chegam ao seu servidor, por isso nunca são contados. Segundo, o destino fica efetivamente congelado. Se mudar o destino do link, qualquer pessoa que já guardou o 301 em cache continua a aterrar no endereço antigo até que a sua cache expire, o que não controla.
Um 302 Found (e o seu primo mais estrito 307 Temporary Redirect) diz ao browser que isto é temporário: volte a perguntar da próxima vez. O browser não guarda o mapeamento em cache, por isso cada clique volta a solicitar o link curto ao servidor. Essa viagem de rede extra é exatamente o que uma ferramenta de links quer. Cada clique chega à sua infraestrutura, por isso cada clique é contável, e porque o servidor resolve o destino de novo de cada vez, pode mudar o destino de um link e ter o novo alvo a tomar efeito no próximo clique. O custo é uma viagem de rede por clique, que uma borda bem construída mantém em milissegundos de um dígito.
É por isso que a Elido usa por defeito um 302. Destinos editáveis e dados de cliques precisos são o ponto central de um link gerido, e um 301 troca ambos por uma otimização de cache que normalmente não quer. O RFC 7231 especifica que um 301 é guardado em cache por defeito enquanto um 302 não é armazenado a menos que os cabeçalhos o indiquem, que é precisamente o comportamento que os dois casos de uso exigem. Há casos estreitos em que um redirect permanente está correto - uma migração de domínio verdadeira, por exemplo - mas para links curtos rastreáveis e editáveis, o redirect temporário é o padrão correto.
Caching na Borda para Baixa Latência#
Um redirect é síncrono e bloqueante. O browser do visitante fica parado no link curto até que o redirect chegue, e só então pode começar a carregar a página que realmente importa. Cada milissegundo gasto a resolver o slug é um milissegundo adicionado à espera do visitante. É por isso que os encurtadores sérios empurram a consulta o mais próximo possível do visitante.
A Elido executa o handler de redirect em pontos de presença de borda em Frankfurt, Ashburn e Singapura, com o tráfego encaminhado para o mais próximo. O handler está escrito em Go sobre fasthttp, escolhido porque o seu caminho de pedido sem alocação mantém as pausas de garbage-collection previsíveis sob carga sustentada. Combinado com a cache em memória, isto mantém os redirects num p95 abaixo de 15ms num acerto de cache, medido no POP: aproximadamente 4,8ms de mediana em Frankfurt, subindo para cerca de 14ms p95 em Singapura onde a geografia é mais ampla. A maior parte desse orçamento é trânsito físico de rede - a distância inevitável entre o visitante e o POP mais próximo, que é a parte que não se pode otimizar em software. Documentámos o orçamento de latência completo e como cada região mede em o artigo sobre p95 abaixo de 15ms.
Colocar a consulta na borda em vez de num único servidor central é a diferença entre um redirect que parece instantâneo e um que acrescenta uma paragem visível. É também por que razão o encaminhamento de borda anycast supera uma configuração apenas com DNS para este fluxo de trabalho - uma comparação que aprofundamos em POPs de borda versus encaminhamento apenas com DNS. A versão curta: a rede faz a geografia, e a cache faz a velocidade.
Contar o Clique Sem Atrasar o Redirect#
Um encurtador que apenas redirecionasse seria um serviço de redirect. O que o torna uma ferramenta de gestão de links é que conta cada clique e diz quem clicou, de onde, em que dispositivo. A parte difícil é fazer isso sem fazer o visitante esperar.
A resposta é desacoplar os dois completamente. Quando o handler de redirect resolve um slug, envia a resposta 302 imediatamente. Registar o clique acontece depois, como trabalho fire-and-forget. O handler acrescenta um evento de clique - slug, timestamp, um IP truncado, um hash do user-agent - a uma fila de mensagens e continua. Não espera que a escrita confirme. Se a fila estiver brevemente indisponível, o clique é descartado em vez de o redirect ser atrasado; tomámos a decisão deliberada de que perder um clique sob falha de infraestrutura é aceitável e falhar um redirect não é.
A Elido usa o Redpanda como essa fila. Um consumidor separado - o ingestor de cliques - lê eventos da fila e escreve-os no ClickHouse, uma base de dados colunar construída para o tipo de fluxo de trabalho de alto volume de acrescentar e agregar que a análise de cliques representa. O redirect do visitante já concluiu milissegundos antes; a linha de análise aterra alguns segundos depois, completamente fora do caminho quente. Explicamos o design da fila em ingestão de cliques fire-and-forget e por que razão um armazém colunar supera o Postgres para isto em por que usamos ClickHouse para análise de cliques.
Este desacoplamento é a razão pela qual a sua análise pode ser detalhada sem ser lenta. O caminho de redirect mantém-se leve porque nenhuma da contagem, pontuação ou agregação acontece enquanto o visitante espera.
Juntando Tudo#
Um encurtador de URL, do início ao fim, é uma sequência curta. Cria um link e o encurtador armazena um mapeamento slug-para-destino no Postgres, gerando ou validando o slug como uma chave única. Um visitante clica, o pedido aterra no POP de borda mais próximo, e o handler resolve o slug a partir de uma cache em memória, caindo para Redis e depois para a base de dados apenas num miss. Devolve um 302 com o destino no cabeçalho Location, para que o clique seja contável e o destino fique editável. Depois dispara o evento de clique para uma fila para um consumidor separado armazenar, sem fazer ninguém esperar.
Cada peça é individualmente simples. A engenharia está nos rácios e nos orçamentos: um fluxo de trabalho com muitas leituras que quer uma cache, um teto de latência que quer a borda, e um requisito de análise que quer ficar fora do caminho quente. Se quiser construir sobre isto diretamente, a funcionalidade de Smart Links expõe a camada de regras, a API e SDKs permitem criar links a partir de código, e a página de soluções para developers e os documentos de arquitetura edge-redirect aprofundam as peças móveis. Se está a avaliar uma ferramenta em vez de construir uma, os nossos artigos sobre o que é um encurtador de URL e se os encurtadores de URL são seguros cobrem o terreno do lado do utilizador, e a página de preços explica onde o nível gratuito termina.