Nesta página, descrevemos os métodos para calcular as configurações corretas para diminuir a latência das conexões TCP em Google Cloud e em cenários híbridos. Esta página também ajuda a entender maneiras de melhorar a latência de conexão entre processos no Google Cloud.
A arquitetura de microsserviços moderna defende que os desenvolvedores construam pequenos serviços com uma única responsabilidade. Os serviços precisam se comunicar usando TCP ou UDP, de acordo com as expectativas de confiabilidade do sistema. Portanto, é essencial que os sistemas baseados em microsserviços se comuniquem com confiabilidade e baixa latência.
OGoogle Cloud oferece confiabilidade e baixa latência por meio de uma rede global, o que significa que os usuários do seu aplicativo também podem se tornar globais. Ter uma rede global significa que você cria uma rede de nuvem privada virtual (VPC) que abrange regiões e zonas. Os aplicativos podem se conectar entre regiões e zonas sem sair da rede do Google Cloud .
Os aplicativos que tenham sido criados para um ambiente tradicional de data center podem apresentar desempenho lento quando são transferidos para um ambiente de nuvem híbrida, ou seja, quando alguns dos componentes do aplicativo são executados em um data center corporativo e outros são executados na nuvem. Um desempenho lento pode ser resultado de vários fatores. O foco deste artigo são latências de ida e volta e como a latência afeta o desempenho do TCP em aplicativos que movimentam uma quantidade considerável de dados em qualquer parte da rede.
Otimizar o desempenho do TCP
O problema: latência e comportamento do TCP
O TCP usa um mecanismo de gestão de janelas para evitar que um remetente rápido ultrapasse um receptor lento. O receptor anuncia quantos dados o remetente precisa enviar antes de aguardar uma atualização de janela por parte do receptor. Dessa forma, se um aplicativo receptor não conseguir receber dados na conexão, haverá um limite na quantidade de dados que podem ficar enfileirados aguardando o aplicativo.
A janela TCP permite o uso eficiente de memória nos sistemas de envio e recebimento. Como o aplicativo receptor consome dados, as atualizações da janela são enviadas para o remetente. O menor tempo de atualização de uma janela é uma ida e volta. Isso leva à seguinte fórmula para um dos limites no desempenho da transferência em massa de uma conexão TCP:
Capacidade <= tamanho da janela / latência do tempo de ida e volta (RTT, na sigla em inglês)
No design original do TCP, essa janela tem um tamanho máximo de 65535 bytes (64 KiB - 1). Essa era a quantidade máxima de dados que o remetente poderia enviar antes que o remetente recebesse uma atualização de janela para permitir o envio de mais dados.
Alterações no TCP desde sua introdução
Desde que o TCP foi introduzido, alguns recursos importantes foram alterados:
- As velocidades de rede típicas aumentaram em quatro ordens de grandeza.
- A memória típica em um sistema aumentou em quatro ordens de grandeza.
O resultado da primeira alteração é que os tamanhos originais de janela TCP levaram a um uso ineficiente dos recursos da rede. Um remetente enviava o equivalente a uma janela de dados na melhor velocidade possível para as condições da rede e ficava ocioso por um período considerável de tempo enquanto aguardava a atualização da janela TCP. O resultado da segunda alteração é que os remetentes e os receptores podem usar mais memória na rede para resolver a limitação exposta pela primeira alteração.
O diagrama a seguir ilustra esse intercâmbio.
O remetente não pode utilizar totalmente a rede porque está aguardando a atualização da janela TCP para enviar mais dados.
Como enviar mais dados por vez
A solução é enviar mais dados por vez. À medida que a largura de banda da rede aumenta, mais dados cabem no canal (rede) e, à medida que ele fica mais longo, mais tempo leva para que o recebimento dos dados seja reconhecido. Essa relação é conhecida como produto de atraso de largura de banda (BDP, na sigla em inglês) e é calculada com a multiplicação da largura de banda pelo tempo de ida e volta (RTT, na sigla em inglês). O resultado é um valor que especifica o número ideal de bits a serem enviados para preencher o canal. Esta é a fórmula:
BDP (bits) = largura de banda (bits/segundo) * RTT (segundos)
O BDP calculado é usado como tamanho de janela TCP para otimização.
Por exemplo, imagine uma rede de 10 Gbps com um RTT de 30 milissegundos. Para o tamanho da janela, use o valor do tamanho de janela TCP original (65535 bytes). Esse valor não chega nem perto de aproveitar a capacidade da largura de banda. O desempenho máximo de TCP possível neste link é:
(65535 bytes * 8 bits/byte) = largura de banda * 0,030 segundo
largura de banda = (65535 bytes * 8 bits/byte)/0,030 segundo
largura de banda = 524280 bits/0,030 segundo
largura de banda = 17476000 bits/segundo
Explicando de outra maneira, estes valores resultam em uma capacidade de mais de 17 Mbits por segundo, que é uma pequena fração da amplitude de 10 Gbps da rede.
A solução: dimensionamento do tamanho da janela TCP
Para resolver as limitações de desempenho impostas pelo design original do tamanho da janela TCP, foram introduzidas extensões no protocolo TCP que permitem que o tamanho da janela seja dimensionado para valores muito maiores. O dimensionamento da janela é compatível com janelas de até 1.073.725.440 bytes, ou quase 1 GiB. Esse recurso é descrito na RFC 7323 como opção de escala da janela TCP.
As extensões de escala de janela expandem a definição da janela TCP para usar 30 bits e, em seguida, usam um fator de escalonamento implícito para transportar esse valor de 30 bits no campo de janela de 16 bits do cabeçalho TCP. Para ver se o recurso está ativado em sistemas baseados em Linux, use este comando:
sudo sysctl net.ipv4.tcp_window_scaling
Todas as máquinas virtuais Linux têm esse recurso ativado por
padrão. Google Cloud Um valor de retorno de 1
indica que a opção está ativada. Se o
recurso estiver desativado, ative-o usando o seguinte comando:
sudo sysctl -w net.ipv4.tcp_window_scaling=1
Taxa de transferência com tamanho de janela maior
Use o exemplo anterior para mostrar a vantagem de ter o escalonamento de janelas. Como antes, suponha uma rede de 10 Gbps com latência de 30 milissegundos e calcule um novo tamanho de janela usando esta fórmula:
(Velocidade do link * latência) / 8 bits = tamanho da janela
Se você inserir os números do exemplo, terá:
(10 Gbps * 30 ms/1000 seg)/8bits/byte = tamanho da janela
(10.000 Mbps * 0,030 segundo)/8 bits/byte = 37,5 MB
Aumentar o tamanho da janela TCP para 37 MB pode incrementar o limite teórico de desempenho da transferência em massa do TCP para um valor que se aproxime da capacidade da rede. Naturalmente, outros fatores podem limitar o desempenho (como sobrecarga do sistema, tamanho médio do pacote e quantidade de fluxos adicionais que compartilham o link), mas o tamanho da janela atenua substancialmente os limites impostos pelo restrito tamanho de janela anterior.
Como configurar os ajustáveis do Linux para alterar o tamanho da janela TCP
No Linux, o tamanho da janela TCP é afetado pelos seguintes
ajustáveis sysctl(8)
:
net.core.rmem_max
net.core.wmem_max
net.ipv4.tcp_rmem
net.ipv4.tcp_wmem
Os dois primeiros ajustáveis afetam o tamanho máximo da janela TCP para aplicativos que tentam controlar o tamanho da janela TCP diretamente, limitando a solicitação dos aplicativos a nada mais que esses valores. Os próximos dois ajustáveis afetam o tamanho da janela TCP para aplicativos que permitem que o ajuste automático do Linux faça o trabalho.
O valor ideal de tamanho de janela depende de circunstâncias específicas, mas um ponto de partida é o BDP (produto de atraso de largura de banda) maior para os caminhos que o sistema provavelmente utilizará para enviar dados. Nesse caso, siga estas etapas para definir os ajustáveis:
- Confira se você tem privilégios raiz.
Consiga as configurações atuais do buffer. Salve-as caso você queira reverter essas alterações.
sudo sysctl -a | grep mem
Defina uma variável de ambiente como o novo tamanho de janela TCP a ser utilizado:
MaxExpectedPathBDP=8388608
Defina o tamanho máximo do buffer de recebimento do sistema operacional para todos os tipos de conexões:
sudo sysctl -w net.core.rmem_max=$MaxExpectedPathBDP
Defina o tamanho máximo do buffer de envio do sistema operacional para todos os tipos de conexões:
sudo sysctl -w net.core.wmem_max=$MaxExpectedPathBDP
Defina as configurações do buffer de memória de recebimento TCP (
tcp_rmem
):sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 $MaxExpectedPathBDP"
A configuração
tcp_rmem
usa três valores:- O tamanho mínimo do buffer de recebimento que pode ser alocado para um soquete TCP.
Neste exemplo, o valor é
4096
bytes. - O tamanho padrão do buffer de recebimento, que também modifica o
valor
/proc/sys/net/core/rmem_default
usado por outros protocolos. No exemplo, o valor é87380
bytes. - O tamanho máximo do buffer de recebimento que pode ser alocado para um soquete TCP.
No exemplo, é o valor definido por você anteriormente (
8388608
bytes).
- O tamanho mínimo do buffer de recebimento que pode ser alocado para um soquete TCP.
Neste exemplo, o valor é
Defina as configurações do buffer de memória de envio TCP (
tcp_wmem
):sudo sysctl -w net.ipv4.tcp_wmem="4096 16384 $MaxExpectedPathBDP"
A configuração
tcp_wmem
usa três valores:- O espaço mínimo do buffer de envio TCP disponível para um único soquete TCP.
- O espaço padrão do buffer permitido para um único soquete TCP.
- O espaço máximo do buffer de envio do TCP.
Defina os ajustáveis para que as conexões subsequentes usem os valores especificados:
sudo sysctl -w net.ipv4.route.flush=1
Para manter estas configurações durante as reinicializações, anexe os comandos definidos
anteriormente ao arquivo /etc/sysctl.conf
:
sudo bash -c 'cat << EOF >> /etc/sysctl.conf
net.core.rmem_max=8388608
net.core.wmem_max=8388608
net.ipv4.tcp_rmem=4096 87380 8388608
net.ipv4.tcp_wmem=4096 16384 8388608
net.ipv4.route.flush=1
EOF'
Como testar o RTT com um tamanho de janela atualizado
Quando o tamanho da janela TCP é grande o suficiente para usar o BDP, a imagem muda, como mostrado neste diagrama:
O tamanho da janela TCP sempre pode ser adaptado com base nos recursos disponíveis para o processo envolvido e o algoritmo do TCP em uso. Como mostrado no diagrama, o dimensionamento de janelas permite que uma conexão vá além do tamanho da janela de 65 KiB definido na especificação original do TCP.
Faça o teste. Primeiro, certifique-se de ter feito alterações no tamanho da janela TCP em um computador local e um remoto ao definir os ajustáveis nas duas máquinas. Em seguida, execute os seguintes comandos:
dd if=/dev/urandom of=sample.txt bs=1M count=1024 iflag=fullblock
scp sample.txt your_username@remotehost.com:/some/remote/directory
O primeiro comando cria um arquivo sample.txt
de 1 GB com dados aleatórios. O
segundo comando copia este arquivo da sua máquina local para uma máquina remota.
Observe a saída do comando scp
no console, que exibe a largura de banda em Kbps.
Há uma diferença considerável nos resultados do tamanho da janela TCP
antes e depois das alterações.
Otimizar a capacidade de recuperação da rede TCP usando o Protective ReRoute
O Protective ReRoute (PRR) é uma técnica baseada em host para rotear pacotes em torno de falhas em uma rede de vários caminhos. O Google implanta o PRR em toda a frota e complementa os mecanismos padrão de resiliência da rede para melhorar a disponibilidade geral dela.
A PRR está disponível para clientes do Google Cloud em dois modos: hipervisor e convidado. Todos os clientes recebem automaticamente a PRR no modo hipervisor sem precisar fazer nada. Google Cloud
O PRR no modo hypervisor protege a grande maioria do tráfego, com algumas exceções:
Se uma instância tiver um fan-out de tráfego enorme (por exemplo, se uma instância estiver enviando ativamente pacotes para milhares de instâncias entre regiões ao mesmo tempo), nem todos os pacotes serão protegidos.
O PRR no modo hipervisor protege segmentos importantes do caminho de rede, mas não é totalmente de ponta a ponta.
O PRR no modo hypervisor reage em segundos de um único dígito.
A PRR do modo visitante pode ser usada para aplicativos críticos que são particularmente sensíveis a eventos de rede de curta duração, têm grandes padrões de fanout, são altamente sensíveis à perda de pacotes ou exigem o tempo de recuperação de rede mais rápido possível (em escala de tempo RTT). Para adotar a PRR do modo visitante, atenda às seguintes condições:
- A instância de computação precisa executar o Linux com kernel 4.20 ou mais recente. Para verificar a versão do kernel do Linux, execute o comando
uname -r
na instância de computação. - O seguinte
sysctl
precisa estar ativado:/proc/sys/net/ipv6/auto_flowlabels
. Essesysctl
geralmente é ativado por padrão. - Se usado com a interface de rede VirtIO, apenas o tráfego de rede IPv6 será protegido.
- Se usado com a interface de rede gVNIC, o tráfego de rede IPv4 e IPv6 será protegido.
A seguir
- Leia a postagem do blog sobre cinco etapas para melhorar o desempenho da rede do Google Cloud .
- Saiba mais sobre produtos de rede global (em inglês)
- Leia mais sobre níveis de rede em Google Cloud.
- Saiba como comparar o desempenho da rede.