Ubuntu 14.04
apt-get install nginx apache2-utils
Em seguida, vi /etc/nginx/sites-enabled/default
para estes conteúdos:
server {
listen 80 default_server;
location / {
return 200 "Ok";
}
}
service nginx restart
Em exibição:
ab -c 500 -k -n 100000 127.0.0.1/
Eu obtenho o resultado:
Percentage of the requests served within a certain time (ms)
50% 0
66% 0
75% 0
80% 0
90% 0
95% 0
98% 14
99% 489
100% 3065 (longest request)
Ok, então recebo a maioria das respostas muito rapidamente (o que é esperado), mas cerca de 1% (quase 1000 solicitações) de respostas são muito lentas. (0.5s - 3s)
Por que isso está acontecendo? Como encontrar a fonte do problema? Eu acho que o kernel / sysctl, mas como descobrir exatamente o que está acontecendo?
UPDATE1
Eu tentei substituir ab
por siege
e o resultado é o mesmo.
siege -c 500 -r 200 -b 127.0.0.1/
....
Concurrency: 240.67
Successful transactions: 100000
Failed transactions: 0
Longest transaction: 1.50
Shortest transaction: 0.00
Eu tentei alterar algumas variáveis em nginx
e reiniciar o servidor após cada alteração e re-executar ab
.
worker_processes 10;
worker_connections 7680;
multi_accept on;
events { use select; }
events { use poll; }
events { use epoll; }
Eu tentei ajustar sysctl
e executar o teste novamente toda vez:
net.core.somaxconn=5120 # including listen directive backlog in nginx
net.core.netdev_max_backlog=5120
Eu aumentei o número de arquivos abertos para 5000000 e testei novamente.
Eu tentei alguns outros métodos de controle de congestionamento tcp e executei novamente o teste a cada vez.
sysctl -w net.ipv4.tcp_congestion_control=hybla
sysctl -w net.ipv4.tcp_congestion_control=illinois
sysctl -w net.ipv4.tcp_congestion_control=lp
sysctl -w net.ipv4.tcp_congestion_control=probe
sysctl -w net.ipv4.tcp_congestion_control=scalable
sysctl -w net.ipv4.tcp_congestion_control=vegas
sysctl -w net.ipv4.tcp_congestion_control=veno
sysctl -w net.ipv4.tcp_congestion_control=westwood
sysctl -w net.ipv4.tcp_congestion_control=yeah
Eu tentei mais sysctl vars e executei novamente o teste toda vez.
sysctl -w net.core.rmem_max=67108864
sysctl -w net.ipv4.tcp_rmem='4096 87380 33554432'
sysctl -w net.ipv4.tcp_wmem='4096 65536 33554432'
sysctl -w net.core.netdev_max_backlog=30000
sysctl -w net.ipv4.tcp_congestion_control=htcp
sysctl -w net.ipv4.tcp_mtu_probing=1
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
sysctl -w net.ipv4.tcp_rmem='4096 87380 67108864'
sysctl -w net.ipv4.tcp_wmem='4096 65536 67108864'
sysctl -w net.core.netdev_max_backlog=250000
sysctl -w net.ipv4.tcp_congestion_control=htcp
sysctl -w net.ipv4.tcp_mtu_probing=1
Finalmente, eu baixei golang
e compilei o servidor e testei ab
contra este servidor básico - tudo é o mesmo.
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "OK")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
go run test.go
Nada parece afetar esse 1%.
UPDATE2
Ok, isso pode ter algo a ver com a saturação da CPU. Na máquina GCE de 16 núcleos, o efeito é muito melhor e menos perceptível. O teste original foi feito na instância Ocean Digital de 1 núcleo.
UPDATE3
Sim, tem que ser algo com CPU. Nenhum efeito no GCE de 4 núcleos. (Adicionado como resposta)