O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho

O protocolo QUIC é extremamente interessante de assistir, e é por isso que adoramos escrever sobre ele. Mas se as publicações anteriores sobre QUIC eram mais de natureza histórica (história local, se você preferir) e hardware, hoje temos o prazer de publicar uma tradução de um tipo diferente - falaremos sobre a aplicação real do protocolo em 2019. Além disso, não se trata de uma pequena infraestrutura baseada numa chamada garagem, mas sim da Uber, que opera em quase todo o mundo. Como os engenheiros da empresa tomaram a decisão de usar o QUIC na produção, como realizaram os testes e o que viram depois de implementá-lo na produção – abaixo do corte.

As imagens são clicáveis. Gostar de ler!

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho

A Uber tem uma escala global, nomeadamente 600 cidades de presença, em cada uma das quais a aplicação depende inteiramente da Internet sem fios de mais de 4500 operadores móveis. Os usuários esperam que o aplicativo não seja apenas rápido, mas em tempo real – para conseguir isso, o aplicativo Uber precisa de baixa latência e uma conexão muito confiável. Infelizmente, mas a pilha HTTP / 2 não funciona bem em redes sem fio dinâmicas e propensas a perdas. Percebemos que, neste caso, o baixo desempenho está diretamente relacionado às implementações de TCP nos kernels do sistema operacional.

Para resolver o problema, aplicamos QUIC, um protocolo moderno de multiplexação de canais que nos dá mais controle sobre o desempenho do protocolo de transporte. Atualmente o grupo de trabalho IETF padroniza QUIC como HTTP / 3.

Após extensos testes, concluímos que a implementação do QUIC em nossa aplicação resultaria em latências finais mais baixas em comparação ao TCP. Observamos uma redução na faixa de 10-30% para o tráfego HTTPS nas aplicações de motoristas e passageiros. O QUIC também nos deu controle de ponta a ponta sobre os pacotes do usuário.

Neste artigo, compartilhamos nossa experiência na otimização de TCP para aplicativos Uber usando uma pilha compatível com QUIC.

A mais recente tecnologia: TCP

Hoje, o TCP é o protocolo de transporte mais utilizado para entregar tráfego HTTPS na Internet. O TCP fornece um fluxo confiável de bytes, lidando assim com o congestionamento da rede e as perdas na camada de enlace. O uso generalizado de TCP para tráfego HTTPS se deve à onipresença do primeiro (quase todo sistema operacional contém TCP), à disponibilidade na maioria das infraestruturas (como balanceadores de carga, proxies HTTPS e CDNs) e à funcionalidade pronta para uso que está disponível em quase a maioria das plataformas e redes.

A maioria dos usuários usa nosso aplicativo em trânsito, e as latências finais do TCP não chegam nem perto das demandas de nosso tráfego HTTPS em tempo real. Simplificando, usuários de todo o mundo já passaram por isso. A Figura 1 mostra atrasos nas principais cidades:

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 1: A latência da cauda varia nas principais cidades da Uber.

Embora a latência nas redes indianas e brasileiras tenha sido maior do que nas redes dos EUA e do Reino Unido, a latência de cauda é significativamente maior que a latência média. E isto é verdade mesmo para os EUA e o Reino Unido.

Desempenho TCP pelo ar

O TCP foi criado para com fio redes, isto é, com ênfase em links altamente previsíveis. No entanto, sem fio as redes têm características e dificuldades próprias. Primeiro, as redes sem fio são suscetíveis a perdas devido a interferências e atenuação de sinal. Por exemplo, as redes Wi-Fi são sensíveis a microondas, bluetooth e outras ondas de rádio. As redes celulares sofrem com perda de sinal (caminho perdido) devido à reflexão/absorção do sinal por objetos e edifícios, bem como por interferência do vizinho torres de celular. Isto leva a resultados mais significativos (4-10 vezes) e mais diversificados. atraso de ida e volta (RTT) e perda de pacotes em comparação com uma conexão com fio.

Para combater flutuações e perdas de largura de banda, as redes celulares normalmente usam grandes buffers para picos de tráfego. Isso pode levar a filas excessivas, o que significa atrasos maiores. Muitas vezes o TCP trata esse enfileiramento como um desperdício devido a um tempo limite estendido, de modo que o TCP tende a retransmitir e, assim, preencher o buffer. Este problema é conhecido como bufferbloat (buffer de rede excessivo, inchaço do buffer), e isso é muito problema sério Internet moderna.

Finalmente, o desempenho da rede celular varia de acordo com a operadora, região e horário. Na Figura 2, coletamos os atrasos médios do tráfego HTTPS nas células em um intervalo de 2 quilômetros. Dados coletados de duas grandes operadoras de celular em Delhi, Índia. Como você pode ver, o desempenho varia de célula para célula. Além disso, a produtividade de um operador difere da produtividade do segundo. Isto é influenciado por factores como os padrões de entrada na rede, tendo em conta o tempo e a localização, a mobilidade dos utilizadores, bem como a infra-estrutura da rede, tendo em conta a densidade das torres e a proporção dos tipos de rede (LTE, 3G, etc.).

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 2. Atrasos usando um raio de 2 km como exemplo. Deli, Índia.

Além disso, o desempenho das redes celulares varia com o tempo. A Figura 3 mostra a latência mediana por dia da semana. Também observamos diferenças em menor escala, dentro de um único dia e hora.

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 3. Os atrasos finais podem variar significativamente entre dias, mas para o mesmo operador.

Todos os itens acima fazem com que o desempenho do TCP seja ineficaz em redes sem fio. No entanto, antes de procurar alternativas ao TCP, queríamos desenvolver um entendimento preciso sobre os seguintes pontos:

  • o TCP é o principal culpado pelas latências finais em nossos aplicativos?
  • As redes modernas têm atrasos de ida e volta (RTT) significativos e variados?
  • Qual é o impacto do RTT e da perda no desempenho do TCP?

Análise de desempenho TCP

Para entender como analisamos o desempenho do TCP, vamos dar uma olhada rápida em como o TCP transfere dados de um remetente para um destinatário. Primeiro, o remetente estabelece uma conexão TCP, realizando uma comunicação tripla. aperto de mão: O remetente envia um pacote SYN, espera por um pacote SYN-ACK do receptor e depois envia um pacote ACK. Uma segunda e terceira passagens adicionais são gastas para estabelecer a conexão TCP. O destinatário confirma o recebimento de cada pacote (ACK) para garantir uma entrega confiável.

Se um pacote ou ACK for perdido, o remetente retransmite após um tempo limite (RTO, tempo limite de retransmissão). O RTO é calculado dinamicamente com base em vários fatores, como o atraso esperado do RTT entre o remetente e o destinatário.

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 4. A troca de pacotes por TCP/TLS inclui um mecanismo de retransmissão.

Para determinar o desempenho do TCP em nossas aplicações, monitoramos os pacotes TCP usando tcpdump por uma semana no tráfego de combate proveniente de servidores de ponta indianos. Em seguida, analisamos as conexões TCP usando tcptrace. Além disso, criamos um aplicativo Android que envia tráfego emulado para um servidor de teste, imitando ao máximo o tráfego real. Foram distribuídos smartphones com esta aplicação a vários colaboradores, que recolheram registos ao longo de vários dias.

Os resultados de ambos os experimentos foram consistentes entre si. Vimos altas latências de RTT; os valores da cauda foram quase 6 vezes maiores que o valor mediano; a média aritmética dos atrasos é superior a 1 segundo. Muitas conexões apresentavam perdas, fazendo com que o TCP retransmitisse 3,5% de todos os pacotes. Em áreas congestionadas, como aeroportos e estações ferroviárias, registámos perdas de 7%. Estes resultados lançam dúvidas sobre a sabedoria convencional de que aqueles usados ​​em redes celulares circuitos de retransmissão avançados reduzir significativamente as perdas ao nível do transporte. Abaixo estão os resultados dos testes do aplicativo “simulador”:

Métricas de rede
Significados

RTT, milissegundos [50%,75%, 95%,99%]
[350, 425, 725, 2300]

Divergência RTT, segundos
Em média ~1,2 s

Perda de pacotes em conexões instáveis
Média ~3.5% (7% em áreas sobrecarregadas)

Quase metade dessas conexões teve pelo menos um pacote perdido, a maioria deles pacotes SYN e SYN-ACK. A maioria das implementações TCP usa um valor RTO de 1 segundo para pacotes SYN, que aumenta exponencialmente para perdas subsequentes. O tempo de carregamento do aplicativo pode aumentar porque o TCP demora mais para estabelecer conexões.

No caso de pacotes de dados, valores elevados de RTO reduzem bastante a utilização útil da rede na presença de perdas transitórias em redes sem fio. Descobrimos que o tempo médio de retransmissão é de aproximadamente 1 segundo, com um atraso de cauda de quase 30 segundos. Essas altas latências no nível TCP causaram tempos limite e novas solicitações de HTTPS, aumentando ainda mais a latência e a ineficiência da rede.

Enquanto o percentil 75 do RTT medido foi de cerca de 425 ms, o percentil 75 do TCP foi de quase 3 segundos. Isso sugere que a perda fez com que o TCP demorasse de 7 a 10 passagens para transmitir dados com êxito. Isso pode ser consequência do cálculo ineficiente do RTO, da incapacidade do TCP de responder rapidamente às perdas pacotes mais recentes na janela e a ineficiência do algoritmo de controle de congestionamento, que não distingue entre perdas sem fio e perdas devido ao congestionamento da rede. Abaixo estão os resultados dos testes de perda de TCP:

Estatísticas de perda de pacotes TCP
Valor

Porcentagem de conexões com pelo menos 1 perda de pacote
45%

Porcentagem de conexões com perdas durante a configuração da conexão
30%

Porcentagem de conexões com perdas durante troca de dados
76%

Distribuição de atrasos na retransmissão, segundos [50%, 75%, 95%,99%] [1, 2.8, 15, 28]

Distribuição do número de retransmissões para um pacote ou segmento TCP
[1,3,6,7]

Aplicação de QUIC

Originalmente desenvolvido pelo Google, QUIC é um protocolo de transporte moderno multithread que roda sobre UDP. Atualmente o QUIC está em processo de padronização (já escrevemos que existem, por assim dizer, duas versões do QUIC, curioso pode seguir o link - Aproximadamente. tradutor). Conforme mostrado na Figura 5, o QUIC é colocado em HTTP/3 (na verdade, HTTP/2 sobre QUIC é HTTP/3, que agora está sendo intensamente padronizado). Ele substitui parcialmente as camadas HTTPS e TCP usando UDP para formar pacotes. O QUIC oferece suporte apenas à transferência segura de dados, pois o TLS está totalmente integrado ao QUIC.

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 5: QUIC é executado em HTTP/3, substituindo o TLS, que anteriormente era executado em HTTP/2.

Abaixo estão os motivos que nos convenceram a usar o QUIC para amplificação TCP:

  • Estabelecimento de conexão 0-RTT. O QUIC permite a reutilização de autorizações de conexões anteriores, reduzindo o número de handshakes de segurança. No futuro TLS1.3 suportará 0-RTT, mas um handshake TCP de três vias ainda será necessário.
  • superando o bloqueio HoL. HTTP/2 usa uma conexão TCP por cliente para melhorar o desempenho, mas isso pode levar ao bloqueio HoL (head-of-line). O QUIC simplifica a multiplexação e entrega solicitações ao aplicativo de forma independente.
  • controle de congestão. O QUIC reside na camada de aplicação, facilitando a atualização do algoritmo de transporte principal que controla o envio com base nos parâmetros da rede (número de perdas ou RTT). A maioria das implementações TCP usa o algoritmo CÚBICO, o que não é ideal para tráfego sensível à latência. Algoritmos recentemente desenvolvidos como BBR, modele a rede com mais precisão e otimize a latência. O QUIC permite que você use o BBR e atualize esse algoritmo à medida que ele é usado. melhorando.
  • reposição de perdas. QUIC chama dois TLPs (sonda de perda de cauda) antes do RTO ser acionado - mesmo quando as perdas são muito perceptíveis. Isso é diferente das implementações TCP. O TLP retransmite principalmente o último pacote (ou o novo, se houver) para acionar o reabastecimento rápido. Lidar com atrasos de cauda é particularmente útil para a forma como a Uber opera a sua rede, nomeadamente para transferências de dados curtas, esporádicas e sensíveis à latência.
  • ACK otimizado. Como cada pacote possui um número de sequência exclusivo, não há problema distinções pacotes quando eles são retransmitidos. Os pacotes ACK também contêm tempo para processar o pacote e gerar um ACK no lado do cliente. Esses recursos garantem que o QUIC calcule o RTT com mais precisão. ACK no QUIC suporta até 256 bandas NACK, ajudando o remetente a ser mais resiliente ao embaralhamento de pacotes e a usar menos bytes no processo. ACK seletivo (Sack) no TCP não resolve esse problema em todos os casos.
  • migração de conexão. As conexões QUIC são identificadas por um ID de 64 bits, portanto, se um cliente alterar os endereços IP, o ID de conexão antigo poderá continuar a ser usado no novo endereço IP sem interrupção. Esta é uma prática muito comum para aplicações móveis onde o usuário alterna entre conexões Wi-Fi e celulares.

Alternativas para oQUIC

Consideramos abordagens alternativas para resolver o problema antes de escolher o QUIC.

A primeira coisa que tentamos foi implantar PoPs (Pontos de Presença) TPC para encerrar conexões TCP mais próximas dos usuários. Essencialmente, os PoPs encerram uma conexão TCP com um dispositivo móvel mais próximo da rede celular e fazem proxy do tráfego de volta para a infraestrutura original. Ao encerrar o TCP mais próximo, podemos reduzir potencialmente o RTT e garantir que o TCP responda melhor a um ambiente sem fio dinâmico. No entanto, nossos experimentos mostraram que a maior parte do RTT e das perdas vem de redes celulares e o uso de PoPs não proporciona melhoria significativa de desempenho.

Também analisamos o ajuste dos parâmetros TCP. Configurar uma pilha TCP em nossos servidores de borda heterogêneos foi difícil porque o TCP tem implementações diferentes em diferentes versões de sistemas operacionais. Foi difícil implementar isso e testar diferentes configurações de rede. Não foi possível configurar o TCP diretamente em dispositivos móveis devido à falta de permissões. Mais importante ainda, recursos como conexões 0-RTT e previsão RTT aprimorada são essenciais para a arquitetura do protocolo e, portanto, é impossível obter benefícios significativos ajustando apenas o TCP.

Por fim, avaliamos vários protocolos baseados em UDP que solucionam problemas de streaming de vídeo – queríamos ver se esses protocolos ajudariam em nosso caso. Infelizmente, eles estavam em falta em muitas configurações de segurança e também exigiam uma conexão TCP adicional para metadados e informações de controle.

Nossa pesquisa mostrou que o QUIC é talvez o único protocolo que pode ajudar com o problema do tráfego da Internet, levando em consideração tanto a segurança quanto o desempenho.

Integração do QUIC na plataforma

Para incorporar o QUIC com sucesso e melhorar o desempenho do aplicativo em ambientes de baixa conectividade, substituímos a pilha antiga (HTTP/2 sobre TLS/TCP) pelo protocolo QUIC. Usamos a biblioteca de rede Cronet de Projetos de cromo, que contém a versão original do protocolo Google - gQUIC. Esta implementação também está sendo constantemente aprimorada para seguir as especificações mais recentes da IETF.

Primeiro integramos o Cronet em nossos aplicativos Android para adicionar suporte ao QUIC. A integração foi realizada de forma a reduzir ao máximo os custos de migração. Em vez de substituir completamente a antiga pilha de rede que usava a biblioteca OkHttpGenericName, integramos o Cronet SOB a estrutura da API OkHttp. Fazendo a integração desta forma, evitamos alterações em nossas chamadas de rede (que são utilizadas por Retrofit) no nível da API.

Semelhante à abordagem para dispositivos Android, implementamos o Cronet em aplicativos Uber no iOS, interceptando o tráfego HTTP da rede APIusando Protocolo NSURL. Essa abstração, fornecida pela iOS Foundation, lida com dados de URL específicos do protocolo e garante que possamos integrar o Cronet em nossos aplicativos iOS sem custos significativos de migração.

Concluindo o QUIC no Google Cloud Balancers

No back-end, a conclusão do QUIC é fornecida pela infraestrutura de balanceamento de carga do Google Cloud, que usa alt-svc cabeçalhos em respostas para oferecer suporte ao QUIC. Em geral, o balanceador adiciona um cabeçalho alt-svc a cada solicitação HTTP, e isso já valida o suporte QUIC para o domínio. Quando um cliente Cronet recebe uma resposta HTTP com este cabeçalho, ele usa QUIC para solicitações HTTP subsequentes para esse domínio. Depois que o balanceador conclui o QUIC, nossa infraestrutura envia explicitamente essa ação por HTTP2/TCP para nossos data centers.

Desempenho: Resultados

O desempenho de saída é o principal motivo de nossa busca por um protocolo melhor. Para começar, criamos um estande com emulação de redepara descobrir como o QUIC se comportará em diferentes perfis de rede. Para testar o desempenho do QUIC em redes do mundo real, realizamos experimentos enquanto dirigíamos por Nova Delhi usando tráfego de rede emulado muito semelhante às chamadas HTTP no aplicativo de passageiros.

Experiência 1

Equipamento para o experimento:

  • testar dispositivos Android com pilhas OkHttp e Cronet para garantir que permitimos tráfego HTTPS sobre TCP e QUIC respectivamente;
  • um servidor de emulação baseado em Java que envia o mesmo tipo de cabeçalhos HTTPS em respostas e carrega dispositivos clientes para receber solicitações deles;
  • proxies de nuvem que estão fisicamente localizados perto da Índia para encerrar conexões TCP e QUIC. Enquanto para terminação TCP usamos um proxy reverso em NGINX, foi difícil encontrar um proxy reverso de código aberto para QUIC. Nós mesmos construímos um proxy reverso para QUIC usando a pilha QUIC básica do Chromium e publicado em cromo como código aberto.

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenhoO protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 6. O conjunto de testes rodoviários TCP vs QUIC consistia em dispositivos Android com OkHttp e Cronet, proxies de nuvem para encerrar conexões e um servidor de emulação.

Experiência 2

Quando o Google disponibilizou o QUIC com Balanceamento de carga do Google Cloud, usamos o mesmo inventário, mas com uma modificação: em vez do NGINX, usamos balanceadores de carga do Google para encerrar conexões TCP e QUIC de dispositivos, bem como para rotear o tráfego HTTPS para o servidor de emulação. Os balanceadores são distribuídos em todo o mundo, mas utilizam o servidor PoP mais próximo do dispositivo (graças à geolocalização).

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 7. No segundo experimento, queríamos comparar a latência de conclusão do TCP e do QUIC: usando o Google Cloud e nosso proxy de nuvem.

Como resultado, diversas revelações nos aguardavam:

  • a terminação via PoP melhorou o desempenho do TCP. Como os balanceadores encerram as conexões TCP mais perto dos usuários e são altamente otimizados, isso resulta em RTTs mais baixos, o que melhora o desempenho do TCP. E embora o QUIC tenha sido menos afetado, ele ainda superou o TCP em termos de redução da latência final (em 10 a 30 por cento).
  • caudas são afetadas saltos de rede. Embora nosso proxy QUIC estivesse mais distante dos dispositivos (latência cerca de 50 ms maior) do que os balanceadores de carga do Google, ele apresentou desempenho semelhante: uma redução de 15% na latência versus uma redução de 20% no percentil 99 para TCP. Isto sugere que a transição da última milha é um gargalo na rede.

O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenhoO protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 8: Os resultados de dois experimentos mostram que o QUIC supera significativamente o TCP.

Tráfego de combate

Inspirados pela experimentação, implementamos o suporte QUIC em nossos aplicativos Android e iOS. Realizamos testes A/B para determinar o impacto do QUIC nas cidades onde a Uber opera. Em geral, observamos uma redução significativa nos atrasos finais em ambas as regiões, operadoras de telecomunicações e tipo de rede.

Os gráficos abaixo mostram as melhorias percentuais nas caudas (percentis 95 e 99) por macrorregião e diferentes tipos de rede – LTE, 3G, 2G.
O protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenhoO protocolo QUIC em ação: como a Uber o implementou para otimizar o desempenho
Figura 9. Nos testes de batalha, o QUIC superou o TCP em termos de latência.

Somente para frente

Talvez este seja apenas o começo - o lançamento do QUIC em produção proporcionou oportunidades incríveis para melhorar o desempenho de aplicativos em redes estáveis ​​e instáveis, a saber:

Maior cobertura

Tendo analisado o desempenho do protocolo em tráfego real, vimos que aproximadamente 80% das sessões usaram QUIC com sucesso para todos solicitações, enquanto 15% das sessões usaram uma combinação de QUIC e TCP. Assumimos que a combinação se deve ao tempo limite da biblioteca Cronet de volta ao TCP, uma vez que ela não consegue distinguir entre falhas reais de UDP e más condições de rede. Atualmente estamos procurando uma solução para este problema enquanto trabalhamos para a implementação subsequente do QUIC.

Otimização QUIC

O tráfego de aplicativos móveis é sensível à latência, mas não à largura de banda. Além disso, nossos aplicativos são usados ​​principalmente em redes celulares. Com base em experimentos, as latências finais ainda são altas, mesmo usando um proxy para encerrar TCP e QUIC próximo aos usuários. Estamos procurando ativamente maneiras de melhorar o gerenciamento de congestionamento e melhorar a eficiência dos algoritmos de recuperação de perdas QUIC.

Com essas e diversas outras melhorias, planejamos melhorar a experiência do usuário, independentemente da rede e da região, tornando o transporte de pacotes conveniente e contínuo mais acessível em todo o mundo.

Fonte: habr.com

Adicionar um comentário