Ao integrar um serviço de back-end com o Application Load Balancer, é importante medir o desempenho de um serviço de back-end por si só, na ausência de um balanceador de carga. Os testes de carga em condições controladas ajudam a avaliar as compensações do planeamento da capacidade entre diferentes dimensões do desempenho, como o débito e a latência. Uma vez que o planeamento cuidadoso da capacidade ainda pode subestimar a procura real, recomendamos que use testes de carga para determinar proativamente como a disponibilidade de um serviço é afetada quando o sistema está sobrecarregado.
Objetivos dos testes de carregamento
Um teste de carga típico mede o comportamento visível externamente do serviço de back-end em diferentes dimensões de carga. Seguem-se algumas das dimensões mais relevantes deste teste:
- Débito de pedidos: o número de pedidos publicados por segundo.
- Simultaneidade de pedidos: o número de pedidos processados em simultâneo.
- Débito de ligação: o número de ligações iniciadas pelos clientes por segundo. A maioria dos serviços que usam o protocolo Transport Layer Security (TLS) tem alguma sobrecarga de transporte de rede e negociação de TLS associada a cada ligação, que é independente do processamento de pedidos.
Concorrência de ligações: o número de ligações de clientes processadas em simultâneo.
Latência do pedido: o tempo decorrido total entre o início do pedido e o fim da resposta.
Taxa de erros: frequência com que os pedidos causam erros, como erros HTTP 5xx e ligações fechadas prematuramente.
Para avaliar o estado do servidor sob carga, um procedimento de teste de carga também pode recolher as seguintes métricas de serviço internas:
Utilização de recursos do sistema: os recursos do sistema, como a CPU, a RAM e os identificadores de ficheiros (sockets), são normalmente expressos em percentagem.
A importância destas métricas difere consoante a forma como o serviço é implementado. As aplicações têm um desempenho reduzido, perdem carga ou falham quando esgotam os respetivos recursos. Por conseguinte, torna-se essencial determinar a disponibilidade de recursos quando um anfitrião está sob carga elevada.
Utilização de outros recursos limitados: recursos não pertencentes ao sistema que podem ficar esgotados sob carga, como na camada de aplicação.
Alguns exemplos de tais recursos incluem o seguinte:
- Um conjunto limitado de processos ou threads de trabalho.
- Para um servidor de aplicações que usa threads, é comum limitar o número de threads de trabalho em funcionamento em simultâneo. Os limites do tamanho do conjunto de threads são úteis para evitar o esgotamento da memória e da CPU, mas as predefinições são frequentemente muito conservadoras. Os limites demasiado baixos podem impedir a utilização adequada dos recursos do sistema.
- Alguns servidores usam conjuntos de processos em vez de conjuntos de threads. Por exemplo, um servidor Apache, quando configurado com o modelo de multiprocessamento Prefork, atribui um processo a cada ligação de cliente. Assim, o limite de tamanho do conjunto determina o limite superior da simultaneidade de ligações.
- Um serviço implementado como um frontend para outro serviço que tem um conjunto de ligações de backend de tamanho limitado.
Planeamento de capacidade versus testes de sobrecarga
As ferramentas de teste de carga ajudam a medir diferentes dimensões de escalabilidade individualmente. Para o planeamento da capacidade, determine o limite de carga para o desempenho aceitável em várias dimensões. Por exemplo, em vez de medir o limite absoluto de um pedido de serviço, considere medir o seguinte:
- A taxa de pedidos à qual o serviço pode publicar com uma latência no percentil 99 inferior a um número especificado de milissegundos. O número é especificado pelo SLO do serviço.
- A taxa de pedidos máxima que não faz com que a utilização dos recursos do sistema exceda os níveis ideais. Tenha em atenção que a utilização ideal varia consoante a aplicação e pode ser significativamente inferior a 100%. Por exemplo, com uma utilização de memória máxima de 80%, a aplicação pode conseguir processar picos de carga menores melhor do que se a utilização máxima fosse de 99%.
Embora seja importante usar os resultados dos testes de carga para tomar decisões de planeamento de capacidade, é igualmente importante compreender o comportamento de um serviço quando a carga excede a capacidade. Seguem-se alguns comportamentos do servidor que são frequentemente avaliados através de testes de sobrecarga:
Redução de carga: quando um serviço recebe um número excessivo de pedidos ou ligações de entrada, pode responder abrandando todos os pedidos ou rejeitando alguns pedidos para manter um desempenho aceitável para os restantes. Recomendamos a última abordagem para evitar limites de tempo do cliente antes de receber uma resposta e para reduzir o risco de esgotamento da memória diminuindo a concorrência de pedidos no servidor.
Resiliência contra o esgotamento de recursos: geralmente, um serviço evita falhas devido ao esgotamento de recursos, uma vez que é difícil para os pedidos pendentes progredirem se o serviço tiver falhado. Se um serviço de back-end tiver muitas instâncias, a robustez das instâncias individuais é vital para a disponibilidade geral do serviço. Enquanto uma instância é reiniciada após uma falha, outras instâncias podem sofrer uma carga maior, o que pode causar uma falha em cascata.
Diretrizes gerais de testes
Ao definir os seus exemplos de teste, tenha em atenção as seguintes diretrizes.
Crie testes em pequena escala
Crie testes em pequena escala para medir os limites de desempenho do servidor. Com uma capacidade excessiva do servidor, existe o risco de um teste não revelar os limites de desempenho do próprio serviço, mas pode descobrir gargalos noutros sistemas, como os anfitriões do cliente ou a camada de rede.
Para obter os melhores resultados, considere um teste que use uma única instância de máquina virtual (VM) ou um pod do Google Kubernetes Engine (GKE) para testar o serviço de forma independente. Para alcançar a carga total no servidor, se necessário, pode usar várias VMs, mas lembre-se de que podem complicar a recolha de dados de desempenho.
Escolha padrões de carga de ciclo aberto
A maioria dos geradores de carga usa o padrão de ciclo fechado para limitar o número de pedidos concorrentes e atrasar novos pedidos até que os anteriores estejam concluídos. Não recomendamos esta abordagem porque os clientes de produção do serviço podem não apresentar este comportamento de limitação.
Por outro lado, o padrão de ciclo aberto permite que os geradores de carga simulem a carga de produção enviando pedidos a uma taxa constante, independentemente da taxa à qual as respostas do servidor chegam.
Execute testes com geradores de carga recomendados
Recomendamos os seguintes geradores de carga para o teste de carga do serviço de back-end:
Nighthawk
O Nighthawk é uma ferramenta de código aberto desenvolvida em coordenação com o projeto Envoy. Pode usá-lo para gerar carga do cliente, visualizar referências e medir o desempenho do servidor para a maioria dos cenários de teste de carga de serviços HTTPS.
Teste HTTP/1
Para testar o HTTP/1, use o seguinte comando:
nighthawk_client URI \ --duration DURATION \ --open-loop \ --no-default-failure-predicates \ --protocol http1 \ --request-body-size REQ_BODY_SIZE \ --concurrency CONCURRENCY \ --rps RPS \ --connections CONNECTIONS
Substitua o seguinte:
URI
: o URI a comparar com a referênciaDURATION
: tempo total de execução do teste em segundosREQ_BODY_SIZE
: tamanho do payload POST em cada pedidoCONCURRENCY
: o número total de ciclos de eventos concorrentesEste número deve corresponder à contagem de núcleos da VM do cliente
RPS
: a taxa alvo de pedidos por segundo, por ciclo de eventosCONNECTIONS
: o número de ligações simultâneas, por ciclo de eventos
Veja o exemplo seguinte:
nighthawk_client http://10.20.30.40:80 \ --duration 600 --open-loop --no-default-failure-predicates \ --protocol http1 --request-body-size 5000 \ --concurrency 16 --rps 500 --connections 200
O resultado de cada execução de teste fornece um histograma das latências de resposta. No exemplo da documentação do Nighthawk , repare que a latência do percentil 99 é de aproximadamente 135 microssegundos.
Initiation to completion samples: 9992 mean: 0s 000ms 113us pstdev: 0s 000ms 061us Percentile Count Latency 0 1 0s 000ms 077us 0.5 4996 0s 000ms 115us 0.75 7495 0s 000ms 118us 0.8 7998 0s 000ms 118us 0.9 8993 0s 000ms 121us 0.95 9493 0s 000ms 124us 0.990625 9899 0s 000ms 135us 0.999023 9983 0s 000ms 588us 1 9992 0s 004ms 090us
Teste o HTTP/2
Para testar o HTTP/2, use o seguinte comando:
nighthawk_client URI \ --duration DURATION \ --open-loop \ --no-default-failure-predicates \ --protocol http2 \ --request-body-size REQ_BODY_SIZE \ --concurrency CONCURRENCY \ --rps RPS \ --max-active-requests MAX_ACTIVE_REQUESTS \ --max-concurrent-streams MAX_CONCURRENT_STREAMS
Substitua o seguinte:
URI
: o URI a comparar com a referênciaDURATION
: tempo total de execução do teste em segundosREQ_BODY_SIZE
: tamanho do payload POST em cada pedidoCONCURRENCY
: o número total de ciclos de eventos concorrentesEste número deve corresponder à contagem de núcleos da VM do cliente
RPS
: a taxa alvo de pedidos por segundo para cada ciclo de eventosMAX_ACTIVE_REQUESTS
: o número máximo de pedidos ativos concorrentes para cada ciclo de eventosMAX_CONCURRENT_STREAMS
: o número máximo de streams simultâneas permitidas em cada ligação HTTP/2
Veja o exemplo seguinte:
nighthawk_client http://10.20.30.40:80 \ --duration 600 --open-loop --no-default-failure-predicates \ --protocol http2 --request-body-size 5000 \ --concurrency 16 --rps 500 \ --max-active-requests 200 --max-concurrent-streams 1
ab (ferramenta de referência Apache)
ab
é uma alternativa menos flexível ao Nighthawk, mas está disponível como um pacote em quase todas as distribuições do Linux. ab
só é recomendado para testes rápidos e simples.
Para instalar o ab
, use o seguinte comando:
- No Debian e Ubuntu, execute
sudo apt-get install apache2-utils
. - Em distribuições baseadas no RedHat, execute
sudo yum install httpd-utils
.
Depois de instalar o ab
, use o seguinte comando para o executar:
ab -c CONCURRENCY \ -n NUM_REQUESTS \ -t TIMELIMIT \ -p POST_FILE URI
Substitua o seguinte:
CONCURRENCY
: número de pedidos simultâneos a executarNUM_REQUESTS
: número de pedidos a executarTIMELIMIT
: número máximo de segundos a gastar em pedidosPOST_FILE
: ficheiro local que contém a carga útil HTTP POSTURI
: o URI a comparar com a referência
Veja o exemplo seguinte:
ab -c 200 -n 1000000 -t 600 -p body http://10.20.30.40:80
O comando no exemplo anterior envia pedidos com uma concorrência de 200 (padrão de ciclo fechado) e para após 1 000 000 (um milhão) de pedidos ou 600 segundos de tempo decorrido. O comando também inclui o conteúdo do ficheiro body
como uma carga útil HTTP POST.
O comando ab
produz histogramas de latência de resposta semelhantes aos do Nighthawk, mas a respetiva resolução está limitada a milissegundos, em vez de microsegundos:
Percentage of the requests served within a certain time (ms) 50% 7 66% 7 75% 7 80% 7 90% 92 95% 121 98% 123 99% 127 100% 156 (longest request)