Eu estava fazendo uma pesquisa para um dos próximos projetos no meu trabalho. Eu precisava testar o servidor http se ele pode lidar com 500-1500 solicitações simultâneas.
É mais difÃcil fazer o teste correto do que o servidor correto. O servidor Web não tem nenhum registro no log de erros e pode processar solicitações que enviei com curl durante a execução do teste de carga.
Configuração
Primeiro eu configurei o Nginx com HttpEchoModule , usei o openresty para configurar e compilar facilmente com módulos extras.
Em seguida, crio a configuração para esperar 3 segundos e a resposta com algum texto.
Eu escolhi o nginx como exemplo para comparar com a aplicação real.
location / {
add_header Content-Disposition "inline";
add_header Content-Type "text/plain";
echo_sleep 3;
echo "response text";
}
Testando
Então, começo a testar quantas solicitações ele pode processar ao mesmo tempo:
ab -n 100 -c 100 http://127.0.0.1:7080/
# => ok
ab -n 200 -c 200 http://127.0.0.1:7080/
# => ok
ab -n 500 -c 500 http://127.0.0.1:7080/
# => socket: Too many open files (24)
Provavelmente atingimos a limitação do sistema no máximo de arquivos abertos por processo.
Após o expediente, considero este manual mais útil
http://b.oldhu.com/2012/07/19/increase-tcp-max-connections-on-mac-os-x/
Eu também aumento worker_processes
e worker_connections
no nginx:
worker_processes 2;
events {
worker_connections 4096;
}
worker_rlimit_nofile 8000;
Depois de aumentar as limitações, tente novamente
ab -n 700 -c 700 http://127.0.0.1:7080/
# => ok
ab -n 900 -c 900 http://127.0.0.1:7080/
# => sometimes ok
# => sometimes "apr_socket_recv: Connection reset by peer (54)"
Continue aumentando:
ab -n 1100 -c 1100 http://127.0.0.1:7080/
# => ok or apr_socket_recv error
ab -n 3000 -c 3000 http://127.0.0.1:7080/
# => ok or apr_socket_recv error
ab -n 9000 -c 1000 http://127.0.0.1:7080/
# => apr_socket_recv: Connection reset by peer (54)
# => Total of 455 requests completed
Assim, pude fazer 3.000 solicitações paralelas e obter uma resposta em 3.183 segundos. Mas às vezes falha com erro na ab
ferramenta. E não pode processar quando reqs> conns. Não fiquei feliz com isso, então tento:
- wrk – não funcionou antes, mas depois de reiniciar parece funcionar bem
- Hellperf – Não consegui enviar tantas solicitações quanto desejo
- cerco – estava melhor, mas ainda não conseguia fazer muitos pedidos
O que me deixa feliz é um utilitário chamado boom
Escrito em GO e fonte no github:
https://github.com/rakyll/boom
Não há binário para mac, então precisa compilar:
brew install go
export GOPATH=~/go
go get github.com/rakyll/boom
Usando boom:
~/go/bin/boom -n 8000 -c 1500 -disable-keepalive http://127.0.0.1:7080
Tem:
* boa barra de progresso
* pode lidar com muitas solicitações (por exemplo, 30k reqs com 1500 conns)
* pode lidar com tanta simultaneidade quanto eu preciso
* continuar com erro
* tem um bom diagrama
Barra de progresso:
~/go/bin/boom -n 9000 -c 1500 -disable-keepalive http://127.0.0.1:7080
4500 / 9000 Boooooooooooooooooooooom ! 50.00 % 9s
A saÃda é semelhante a esta:
% ~/go/bin/boom -n 9000 -c 1500 -disable-keepalive http://127.0.0.1:7080
9000 / 9000 Booooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00 %
Summary:
Total: 18.6023 secs.
Slowest: 3.2399 secs.
Fastest: 2.9995 secs.
Average: 3.0652 secs.
Requests/sec: 483.8105
Status code distribution:
[200] 9000 responses
Response time histogram:
2.999 [1] |
3.024 [2383] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
3.048 [1883] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
3.072 [2011] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
3.096 [1219] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
3.120 [7] |
3.144 [188] |∎∎∎
3.168 [147] |∎∎
3.192 [361] |∎∎∎∎∎∎
3.216 [656] |∎∎∎∎∎∎∎∎∎∎∎
3.240 [144] |∎∎
Latency distribution:
10% in 3.0045 secs.
25% in 3.0219 secs.
50% in 3.0493 secs.
75% in 3.0832 secs.
90% in 3.1882 secs.
95% in 3.2031 secs.
99% in 3.2162 secs.
Aplicativo Node.js:
Em seguida, escrevo a mesma funcionalidade em Node.js:
const PORT=7090;
var reqN = 0;
var server = node.http.createServer(function (request, response) {
console.log("Req", reqN++);
setTimeout(function () {
response.setHeader('content-type', 'text/plain');
response.end("response");
}, 3000);
});
server.listen(7090, function(){
console.log("Server listening on: http://localhost:%s", PORT);
});
Faz o mesmo: espera 3 segundos e responde com "response"
corpo.
Eu o executo com o iojs mais recente (1.7.1). O resultado do benchmark é quase o mesmo:
~/go/bin/boom -n 15000 -c 1500 -disable-keepalive http://127.0.0.1:7090
# ...
Response time histogram:
3.000 [1] |
3.039 [6930] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
3.078 [1682] |∎∎∎∎∎∎∎∎∎
3.118 [1204] |∎∎∎∎∎∎
3.157 [644] |∎∎∎
3.196 [1016] |∎∎∎∎∎
3.235 [875] |∎∎∎∎∎
3.275 [1291] |∎∎∎∎∎∎∎
3.314 [890] |∎∎∎∎∎
3.353 [262] |∎
3.393 [205] |∎
Conclusão:
Para pesquisas e desenvolvimentos futuros, prefiro usar boom , é simples, pode lidar com um grande número de solicitações paralelas e tem uma boa saÃda.
Nesta revisão, pulo a ferramenta chamada jMetter, porque tem GUI e fica feia no mac, também porque foi escrita em Java