Como medir a capacidade de processamento e o limite de concorrência através de um proxy com k6 e JMeter
Sumário do artigo
- Introdução: por que saber o limite com antecedência, e não no meio de uma grande extração
- Preparação inicial: ferramentas, requisitos e acessos
- Conceitos básicos em palavras simples
- Passo 1: preparando o alvo de teste e os dados do proxy
- Passo 2: entendendo a metodologia de carga correta
- Passo 3: k6 - script pronto com proxy e etapas de carga
- Passo 4: jmeter - o mesmo cenário com configuração de proxy no plano de teste
- Passo 5: distinguindo o limite do proxy do limite do cliente e do limite do servidor - três verificações
- Passo 6: o que fazer com o resultado - threads, pool e tempo de extração
- Passo 7: ética da carga e modos suaves
- Verificação do resultado: lista de verificação de prontidão
- Erros comuns e soluções
- Recursos adicionais e otimização
- Faq: perguntas frequentes sobre medição de capacidade de processamento através de proxy
- Conclusão
Trabalhar através de um proxy quase sempre esbarra em uma pergunta: quantas solicitações paralelas a combinação "seu cliente - proxy - servidor de destino" realmente aguenta antes que as latências disparem e os erros comecem a aparecer. Este guia vai ensinar você a medir isso com antecedência, e não no meio de uma grande extração, quando o prejuízo é contado em horas de inatividade.
Introdução: por que saber o limite com antecedência, e não no meio de uma grande extração
Imagine uma situação típica. Você inicia uma grande tarefa de coleta de dados públicos através de um pool de proxies. Tudo vai bem nos primeiros milhares de solicitações, mas depois as latências aumentam, parte das solicitações começa a falhar por tempo limite, e você não entende: a culpa é do seu código, do proxy ou do servidor de destino? Nesse ponto, você já perdeu tempo e, possivelmente, dados.
É muito mais sensato realizar um teste de carga controlado com antecedência e encontrar o ponto de degradação. Assim, você pode escolher o número seguro de threads e planejar corretamente o tempo da extração.
O que o leitor vai ganhar no final
Ao concluir este guia, você será capaz de:
- Criar um cenário de carga correto no k6 e executá-lo através de um proxy.
- Repetir o mesmo cenário no JMeter com a configuração de proxy no plano de teste.
- Ler o relatório: entender o RPS (solicitações por segundo), as latências por percentis e a taxa de erros.
- Distinguir o limite do proxy do limite do seu cliente e do limite do servidor de destino.
- Converter os resultados em número de threads, tamanho do pool e tempo esperado da extração.
Para quem é este guia
O material é voltado para engenheiros, analistas de dados e desenvolvedores de nível intermediário. Se você já escreveu scripts simples em JavaScript ou executou programas pela linha de comando, vai se sentir confortável. Para iniciantes, explicamos cada termo em palavras simples.
O que você precisa saber antecipadamente
Bastam habilidades básicas: como abrir um terminal, instalar um programa e editar um arquivo de texto. Conhecimento de HTTP no nível "o que é uma solicitação e uma resposta" é um plus, mas não obrigatório.
Quanto tempo será necessário
A instalação das ferramentas levará cerca de 30-40 minutos. Você executará seu primeiro teste funcional no k6 em uma hora. O ciclo completo com JMeter e análise levará de 3 a 4 horas de trabalho tranquilo.
⚠️ Atenção: Todos os exemplos neste guia são destinados a testar seu próprio ambiente ou recursos cuja carga você tem permissão explícita para realizar. O teste de carga em serviços de terceiros sem consentimento é inaceitável. Falaremos sobre ética em detalhes no final.
Preparação inicial: ferramentas, requisitos e acessos
Antes de medir, precisamos montar o ambiente de trabalho. Aqui listaremos tudo o que é necessário e mostraremos como instalar cada componente.
Ferramentas e acessos necessários
- k6 - ferramenta leve de teste de carga, os cenários são escritos em JavaScript.
- Apache JMeter - ferramenta clássica com interface gráfica baseada em Java.
- Java 17 ou superior - necessário para executar o JMeter.
- Acesso ao proxy Proxeon: endereço, porta, login e senha. Esses dados são obtidos no painel do serviço.
- Alvo de teste - seu próprio ambiente ou um recurso com permissão.
Requisitos de sistema
Para um trabalho confortável, uma máquina com 4 núcleos de CPU e 8 GB de RAM é suficiente. Para cargas altas (milhares de usuários virtuais), o ideal é 8 núcleos e 16 GB. O sistema operacional pode ser Windows, macOS ou Linux; todas as ferramentas são multiplataforma.
Dica: Execute o gerador de carga em uma máquina separada ou em um servidor na nuvem. Assim, você não confunde a carga no seu notebook com a carga no proxy.
Instalação do k6
- Abra o método de instalação oficial para o seu sistema: no macOS, use o gerenciador de pacotes Homebrew com o comando brew install k6.
- No Windows, use o gerenciador de pacotes Chocolatey: choco install k6.
- No Linux, baixe o pacote do repositório do projeto e instale-o com o gerenciador de pacotes do sistema.
- Verifique a instalação com o comando k6 version - você verá o número da versão.
✅ Verificação: Se o comando k6 version mostrar uma linha com a versão e não apresentar o erro "comando não encontrado", a ferramenta está instalada corretamente.
Instalação do Java e do JMeter
- Instale o OpenJDK versão 17 ou superior e verifique com o comando java -version.
- Baixe o arquivo Apache JMeter do site oficial do projeto, na seção de downloads.
- Descompacte o arquivo em uma pasta conveniente, por exemplo, no diretório pessoal.
- Navegue até a subpasta bin dentro do JMeter descompactado.
- Execute o arquivo jmeter (no Linux e macOS) ou jmeter.bat (no Windows).
- Aguarde a janela gráfica aparecer com a árvore do plano de teste à esquerda.
✅ Verificação: Se a janela do JMeter abriu com o elemento "Test Plan" na árvore à esquerda, está tudo pronto.
Backups e preparação do ambiente
Se for testar seu próprio serviço, faça um snapshot ou backup dos dados do ambiente antecipadamente. A carga não deve danificar a produção. Se possível, use uma cópia do ambiente, e não o servidor de produção.
Conceitos básicos em palavras simples
Para ler os relatórios e não se confundir com os termos, vamos revisar os conceitos-chave.
Capacidade de processamento e RPS
Capacidade de processamento (throughput) - é quanto trabalho útil o sistema realiza por unidade de tempo. No contexto HTTP, geralmente é medida em RPS - solicitações por segundo. Quanto maior o RPS com latências aceitáveis, melhor.
Latência e percentis
Latência - o tempo entre o envio da solicitação e o recebimento da resposta. Um valor médio é enganoso, porque solicitações raras e lentas se dissolvem nele. Por isso, usamos percentis.
O percentil p95 significa: 95% das solicitações foram mais rápidas que esse valor, e 5% foram mais lentas. O percentil p99 mostra o comportamento das solicitações mais lentas. São p95 e p99 que melhor refletem a experiência real sob carga.
Taxa de erros e ponto de degradação
Taxa de erros - a porcentagem de solicitações que terminaram sem sucesso: tempo limite, falhas de conexão, códigos de resposta 5xx. Ponto de degradação - o ponto em que o aumento da carga deixa de aumentar o RPS, mas as latências e os erros disparam. Este é o limite que procuramos.
Concorrência e usuários virtuais
Concorrência - quantas solicitações são executadas simultaneamente. No k6, é definida por VU (virtual users, usuários virtuais); no JMeter, pelo número de threads no grupo de threads (Thread Group). Um VU ou thread envia solicitações sequencialmente, e muitos deles criam carga paralela.
Proxy na cadeia de carga
O proxy é um nó intermediário pelo qual suas solicitações passam. Ele tem seu próprio limite de conexões simultâneas e capacidade de processamento. Nosso objetivo é entender em que nível de concorrência esse nó se torna o gargalo.
Dica: Tenha em mente a Lei de Little: o número médio de solicitações simultâneas é aproximadamente igual ao RPS multiplicado pela latência média em segundos. Ela ajuda a estimar rapidamente a concorrência necessária.
Passo 1: Preparando o alvo de teste e os dados do proxy
Objetivo da etapa: obter um URL de destino funcional e uma string de conexão formatada corretamente para o proxy.
- Defina o URL do alvo que você vai testar. Pode ser seu ambiente, por exemplo, https://stend.local/api/health.
- Verifique se o alvo responde de forma rápida e estável a uma única solicitação através do navegador ou da ferramenta curl.
- Obtenha os dados do proxy Proxeon no painel: host, porta, nome de usuário e senha.
- Monte a string de conexão no formato http://USUARIO:SENHA@HOST:PORTA. Por exemplo: http://user:pass@proxy.proxeon.net:8000.
- Teste o proxy com uma única solicitação curl, substituindo os dados do exemplo pelos seus.
Exemplo de solicitação de teste:
curl -x http://user:pass@proxy.proxeon.net:8000 -H "Accept: application/json" https://stend.local/api/health⚠️ Atenção: Nunca armazene o login e a senha do proxy diretamente no código que irá para o repositório. Use variáveis de ambiente. Mostraremos isso nos próximos passos.
Resultado esperado: o curl através do proxy retorna uma resposta correta do seu alvo, sem erros de conexão.
Problemas possíveis: se o curl travar, verifique a porta e o firewall. Se retornar erro de autorização 407, verifique novamente o login e a senha.
✅ Verificação: Você vê o corpo da resposta do alvo, obtido exatamente através do proxy. Isso significa que a cadeia está funcionando.
Passo 2: Entendendo a metodologia de carga correta
Objetivo da etapa: entender por que uma rajada única é inútil e como construir um perfil de carga correto.
Por que uma rajada única engana
Se você disparar mil solicitações de uma só vez, verá um número bonito, mas sem sentido. Essa rajada não mostra o comportamento sustentado. O sistema pode absorver um pico graças aos buffers e depois degradar. Ou, ao contrário, pode engasgar no início por causa de conexões frias.
As três fases de um teste correto
Um teste de carga correto consiste em três fases:
- Aquecimento (warm-up). Nos primeiros 30-60 segundos, aumentamos a carga gradualmente. Os pools de conexão, caches de DNS e estruturas internas são aquecidos. Os dados do aquecimento não entram nas estatísticas finais.
- Crescimento em etapas (ramp-up steps). Aumentamos a concorrência em etapas: por exemplo, 10, 25, 50, 100, 200 VU, permanecendo em cada etapa por 1-2 minutos. Assim, vemos em qual etapa começa a degradação.
- Platô estável (steady state). Fixamos a carga em um nível ligeiramente abaixo do limite e a mantemos por 5-10 minutos. O platô mostra se o sistema é estável sob carga constante, se não há vazamentos e acúmulo de filas.
Dica: Nunca tire conclusões com base nos primeiros 30 segundos do teste. Deixe o sistema atingir o estado estacionário; só então observe os números.
O que registrar em cada etapa
- O RPS alcançado.
- As latências p50, p95, p99.
- A taxa de erros.
- O número de VUs ou threads ativos.
O ponto de degradação é determinado assim: encontramos a etapa após a qual o RPS parou de crescer, enquanto p95 e a taxa de erros começaram a aumentar acentuadamente. A etapa anterior é o seu ponto de trabalho seguro.
✅ Verificação: Você consegue explicar com suas próprias palavras a diferença entre aquecimento e platô e por que o crescimento em etapas é necessário.
Passo 3: k6 - Script pronto com proxy e etapas de carga
Objetivo da etapa: criar e executar um script k6 funcional que percorra aquecimento, etapas e platô através do proxy.
Como o k6 funciona com proxy
O k6 lê o endereço do proxy das variáveis de ambiente HTTP_PROXY e HTTPS_PROXY. Isso é conveniente: você não precisa colocar os dados no script, basta passá-los na execução.
Script pronto load-test.js
Crie um arquivo load-test.js e cole o código a seguir. Substitua o endereço do alvo pelo seu.
import http from 'k6/http'; import { check, sleep } from 'k6'; import { Trend, Rate, Counter } from 'k6/metrics'; const latency = new Trend('req_latency', true); const errors = new Rate('req_errors'); const ok = new Counter('req_ok'); export const options = { discardResponseBodies: true, thresholds: { req_errors: ['rate<0.02'], http_req_duration: ['p(95)<1500', 'p(99)<3000'], }, scenarios: { ramp: { executor: 'ramping-vus', startVUs: 0, stages: [ { duration: '1m', target: 10 }, { duration: '2m', target: 25 }, { duration: '2m', target: 50 }, { duration: '2m', target: 100 }, { duration: '2m', target: 200 }, { duration: '5m', target: 200 }, { duration: '1m', target: 0 }, ], gracefulRampDown: '30s', }, }, }; const TARGET = __ENV.TARGET_URL || 'https://stend.local/api/health'; export default function () { const res = http.get(TARGET, { timeout: '10s', tags: { name: 'target' } }); latency.add(res.timings.duration); const good = check(res, { 'status is 200': (r) => r.status === 200 }); errors.add(!good); if (good) ok.add(1); sleep(0.5); }Como executar o script através do proxy
- Abra o terminal na pasta do script.
- Defina as variáveis de ambiente com o endereço do proxy e o alvo. No Linux e macOS, execute a exportação das variáveis.
- Execute o k6 com o comando de execução do script.
Exemplo de execução no Linux e macOS:
export HTTP_PROXY=http://user:pass@proxy.proxeon.net:8000 export HTTPS_PROXY=http://user:pass@proxy.proxeon.net:8000 export TARGET_URL=https://stend.local/api/health k6 run load-test.jsNo Windows, no PowerShell, as variáveis são definidas com a sintaxe $env:
$env:HTTP_PROXY="http://user:pass@proxy.proxeon.net:8000"; $env:HTTPS_PROXY="http://user:pass@proxy.proxeon.net:8000"; $env:TARGET_URL="https://stend.local/api/health"; k6 run load-test.jsDica: O parâmetro discardResponseBodies desativa o armazenamento dos corpos das respostas na memória. Isso reduz a carga no próprio gerador e ajuda a não confundir sua sobrecarga com o limite do proxy.
Lendo o relatório do k6
Após a conclusão do teste, o k6 mostra um resumo. Observe as linhas-chave:
- http_reqs - o número total de solicitações e o RPS médio entre parênteses. Essa é sua capacidade de processamento.
- http_req_duration - as latências, mostrando avg, min, med, max e percentis p(90), p(95).
- req_errors e http_req_failed - a taxa de erros.
- vus - o número de usuários virtuais no momento.
A linha thresholds mostrará se seus limites foram atendidos. Se houver um X ao lado da linha, o limite foi violado - significa que nessa configuração o teto já foi atingido ou ultrapassado.
⚠️ Atenção: Ajuste os valores de target nas stages de acordo com o seu sistema. O valor 200 VU é apenas um exemplo. Se o seu alvo ou o limite do plano do proxy for menor, comece com etapas mais modestas, por exemplo, até 50.
Resultado esperado: o teste terminou e você vê o resumo com RPS, percentis e taxa de erros.
Problemas possíveis: se todas as solicitações falharem, verifique as variáveis do proxy. Se o gerador estiver usando 100% da CPU, reduza o número de VUs ou execute o teste em uma máquina mais potente.
✅ Verificação: No resumo do k6, http_reqs é diferente de zero e a taxa de erros está abaixo do seu limite, pelo menos nas primeiras etapas.
Passo 4: JMeter - O mesmo cenário com configuração de proxy no plano de teste
Objetivo da etapa: montar um plano equivalente no JMeter com proxy, etapas e coleta de métricas.
Criando o grupo de threads
- No JMeter aberto, clique com o botão direito no elemento Test Plan.
- Selecione Add - Threads (Users) - Thread Group.
- No campo Number of Threads, defina o número máximo de threads, por exemplo, 200.
- No campo Ramp-up period, informe o tempo para atingir a carga total em segundos, por exemplo, 540, para repetir o crescimento em etapas do k6.
- No campo Loop Count, marque Infinite e definiremos a duração com um temporizador e o agendador.
Configuração do proxy em HTTP Request Defaults
Para não configurar o proxy em cada solicitação, definiremos uma única vez.
- Clique com o botão direito no Thread Group e selecione Add - Config Element - HTTP Request Defaults.
- No elemento aberto, encontre a aba com as configurações do servidor proxy.
- No campo Server Name or IP (no bloco Proxy), insira o host do proxy, por exemplo, proxy.proxeon.net.
- No campo Port Number (Proxy), insira a porta, por exemplo, 8000.
- Nos campos Username e Password (Proxy), insira seu login e senha.
Adicionando a própria solicitação HTTP
- Clique com o botão direito no Thread Group e selecione Add - Sampler - HTTP Request.
- No campo Protocol, digite https.
- No campo Server Name or IP, digite o domínio do alvo, por exemplo, stend.local.
- No campo Path, digite o caminho, por exemplo, /api/health.
- No campo Method, deixe GET.
Adicionando o atraso entre solicitações
- Clique com o botão direito no HTTP Request e selecione Add - Timer - Constant Timer.
- No campo Thread Delay, insira 500 milissegundos para repetir o sleep do k6.
Configurando a coleta de métricas
- Clique com o botão direito no Thread Group e adicione Add - Listener - Summary Report.
- Adicione também Add - Listener - Aggregate Report - ele mostra os percentis.
- Para testes longos, não use listeners gráficos; eles consomem memória. Em vez disso, salve os resultados em um arquivo.
Dica: Para testes pesados, execute o JMeter em modo não gráfico pelo terminal. Assim, o gerador gasta recursos na carga, não na renderização de gráficos.
Exemplo de execução em modo não gráfico:
jmeter -n -t plan.jmx -l results.jtl -e -o reportAqui, -n executa sem interface gráfica, -t indica o arquivo do plano, -l o arquivo com os resultados brutos e -e -o cria um relatório HTML na pasta report.
Lendo o relatório do JMeter
Abra o index.html da pasta report. Os principais indicadores:
- Throughput - capacidade de processamento em solicitações por segundo.
- Response Times Percentiles - gráfico dos percentis de latência.
- Error percentage - taxa de erros.
- Active Threads Over Time - como a concorrência cresceu.
⚠️ Atenção: Na autenticação do proxy, o JMeter às vezes exige configuração adicional de autorização Basic. Se você vir erros 407 em massa, adicione o elemento HTTP Authorization Manager com os dados do proxy.
Resultado esperado: O relatório HTML do JMeter abre e mostra throughput, percentis e taxa de erros.
✅ Verificação: Os valores de throughput e percentis no JMeter são comparáveis aos resultados do k6 com as mesmas etapas. Pequenas diferenças são normais.
Passo 5: Distinguindo o limite do proxy do limite do cliente e do limite do servidor - três verificações
Objetivo da etapa: determinar com precisão qual dos três nós se tornou o gargalo.
Ao ver a degradação, é importante entender sua origem. Faça três verificações de controle.
Verificação 1: seu cliente não está no limite?
- Durante o teste, abra o monitor de sistema na máquina geradora.
- Acompanhe o uso de CPU e memória do processo k6 ou JMeter.
- Verifique o limite de descritores de arquivo no Linux com o comando ulimit -n.
Se a CPU do gerador estiver perto de 100% ou você atingir o limite de descritores - a culpa é do cliente, não do proxy. Aumente o limite de descritores, reduza o número de VUs ou use uma máquina mais potente.
Dica: Um sinal de sobrecarga do cliente é o aumento das latências junto com o aumento do uso de CPU do gerador, com RPS constante. O proxy não tem relação com isso.
Verificação 2: o servidor de destino não está no limite?
- Execute um teste curto diretamente, sem proxy, removendo as variáveis HTTP_PROXY e HTTPS_PROXY.
- Compare o RPS e os percentis com os resultados através do proxy.
Se tanto diretamente quanto através do proxy o limite de RPS for quase o mesmo - o gargalo está no servidor de destino. O proxy adiciona apenas uma latência fixa pequena.
⚠️ Atenção: O teste direto deve ser feito apenas contra seu próprio ambiente. Não sobrecarregue recursos de terceiros sem permissão, mesmo para fins de diagnóstico.
Verificação 3: isolando o próprio proxy
- Suba em seu ambiente um stub leve que responda instantaneamente 200 OK com corpo vazio.
- Execute o teste através do proxy contra esse stub.
O stub responde quase instantaneamente, portanto as latências e o limite de RPS agora são determinados principalmente pelo proxy e pela rede. Se o RPS atingir o teto exatamente no stub - você encontrou o limite do proxy.
Vamos resumir a lógica em uma tabela de decisão simples em palavras:
- CPU do gerador alta, RPS não cresce - limite do cliente.
- Diretamente e através do proxy igual - limite do servidor de destino.
- No stub rápido através do proxy o RPS atingiu o teto - limite do proxy.
Resultado esperado: você nomeia o nó específico que limita sua cadeia.
✅ Verificação: Você realizou todas as três verificações e pode justificar onde está o gargalo.
Passo 6: O que fazer com o resultado - threads, pool e tempo de extração
Objetivo da etapa: transformar os números do teste em configurações práticas para sua tarefa de trabalho.
Escolha do número seguro de threads
Considere a etapa antes do ponto de degradação. Suponha que com 100 VU você obteve 180 RPS estáveis, p95 em cerca de 900 ms e erros abaixo de 1%, e com 200 VU o RPS não cresceu, mas p95 saltou para 4 segundos. Então, o ponto de trabalho é cerca de 100 VU, e para ter margem de segurança, use 80-90.
Cálculo do tamanho do pool de proxies
Se um nó de proxy suporta de forma estável N conexões paralelas, e você precisa de M simultâneas, o tamanho mínimo do pool é M dividido por N, arredondado para cima, mais uma margem. Uma margem de 20-30% cobre os momentos em que parte das conexões está ocupada com respostas lentas.
Dica: Sempre inclua margem no pool. As respostas reais são mais lentas que o stub, portanto as conexões são mantidas por mais tempo e a concorrência real é maior do que a calculada.
Estimativa do tempo de extração
A fórmula é simples: o tempo em segundos é igual ao número total de solicitações dividido pelo RPS estável. Se você precisa coletar 1.000.000 de solicitações a 180 RPS estáveis, isso é aproximadamente 5556 segundos, ou cerca de 1 hora e 33 minutos, sem contar pausas e repetições.
- Considere o RPS estável da etapa de trabalho.
- Divida o volume total da tarefa por esse RPS.
- Adicione 15-20% para repetições de solicitações com falha e pausas.
Exemplo de cálculo em pseudocódigo para clareza:
total = 1000000; rps = 180; base_sec = total / rps; final_sec = base_sec * 1.2;