问题
我无法达到每秒 6k 个请求。
我遇到很多超时问题。
我的响应时间高达 26 秒。
介绍
我正在设置一个服务器,用于托管一个 100MB 的静态网站。
问题是,我必须连续 5 天处理大约 8000 个持续请求。
我做了以下设置:
HAProxy -> Varnish -> Nginx -> Staticfiles
HAProxy 处理端口 80 上的连接(很快也会处理端口 443 上的连接),将请求传输到 Varnish,Varnish 将从缓存中提供文件。我已将 Nginx 设置为expires 7d;
。因此 Narnish 每 7 天将向 Nginx 请求一次静态文件。
- 我在 Nginx 上使用最高压缩级别,因此 Varnish 存储高度压缩的静态文件
gzip_comp_level 9;
。 - 我已在 Nginx 中将静态文件的 ttl 设置为 7 天
expires 7d;
。 - 我在 Varnish 中设置了大量的线程(至少我认为是这样)
thread_pools=8 thread_pool_max=4000
。 - 我为 Varnish 设置了不太大也不太小的内存(静态文件总共不超过 100MB)
malloc,512m
。 - 我已经在 HAProxy 中设置了 maxconn 的最大数量
maxconn 65000
。 - 我尝试使用 sysctl 配置,但不确定它是否改变了什么,这就是为什么我认为我的问题来自我的配置。
- 我相信 HAProxy
maxconn 65000
不会限制。我认为 Varnish 会限制我的请求,但我不知道如何确认。
我的服务器设置如下:
Intel(R) Xeon(R) CPU E3-1245 V2 @ 3.40GHz
数量:8
缓存:8192 KB
速度:1764 MHz
RAM 2 x 8192 MB
配置文件
Nginx
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_comp_level 9;
gzip_buffers 16 16k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 127.0.0.1:82 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
location / {
expires 7d;
add_header Cache-Control "public";
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
}
漆
//DEAMON
DAEMON_OPTS="-a localhost:6081 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-p thread_pools=8 \
-p thread_pool_min=100 \
-p thread_pool_max=4000 \
-s malloc,512m"
//default.vcl
# new 4.0 format.
vcl 4.0;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "82";
}
HAProxy
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
maxconn 65000
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
userlist users
group admin
user username insecure-password password groups admin
frontend static_https
bind *:80
mode http
acl aclok http_auth_group(users) admin
#http-request auth realm admin if !aclok
default_backend static_varnish
backend static_varnish
mode http
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server varnish 127.0.0.1:6081 check
系统配置参数
net.ipv4.tcp_max_syn_backlog = 10240
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 2048 61000
net.core.netdev_max_backlog = 40000
net.ipv4.tcp_max_tw_buckets = 400000
net.ipv4.tcp_max_orphans = 60000
net.core.somaxconn = 40000
编辑
loader.io 配置负载测试和结果
答案
@狐狸
为什么 HAProxy 位于 Varnish 前面?
我的客户绝对希望浏览器中显示 https。因此,我认为应该将处理 SSL 证书的工作委托给 HAProxy。
试验时负载是多少?
我还没有设置监控工具,但是从我运行的上次测试来看,通过查看 htop 我可以告诉:
- proc:平均值 25%
- ram:平均值 1070MB。
你如何測試?
我正在使用 loader.io,它创建了 10000 个客户端,并让它们请求 1 分钟。您可以在此处查看完整的测试:http://ldr.io/1eLKrrT
使用保持活动?
我不确定 loader.io 是如何做的。
什么硬件?
我无法告诉你比上面写的更多内容,除非有办法使用一些 shell 命令?
测试是否通过Accept-Encoding: gzip?
我在您发表评论后将其添加到 loader.io 中,但它并没有改变任何东西。
缓存命中率是多少?
这是一个非常好的问题,但我不知道在哪里可以看到?
答案1
我将以开放式回答的方式开始回答这个问题。因为我无法一次性回答所有问题,而且还会有后续问题。
首先,你有点把事情复杂化了。通过 nginx、varnish 和 haproxy 提供静态内容可能会造成很多不必要的开销(更多 TCP 连接、更多内容切换、更多内存使用等)。
实际上,直接使用 nginx 可能会获得更好的性能。由于所有内容都会放入内存中,因此 nginx 无论如何都会从内存中提供这些文件(这要归功于操作系统缓存)。使用 nginxopen_file_cache
甚至可以避免文件系统开销。Varnish 可能会为纯 HTTP 提供略微更好的性能。
对于您的情况,我会从 KISS 方法开始 - 普通的 nginx,将其调整到最佳性能。然后添加 SSL 并将其调整到最佳性能(keep-alives、ssl 会话缓存)。如果您觉得仅使用 nginx 的性能不够好,那么请尝试找出您的真正瓶颈是什么以及如何缓解它(使用什么软件)。
还有基准测试。我会从本地的东西开始,比如 JMeter、httperf,或者至少是 Apache Bench。这可以帮助你排除所有与互联网有关的东西。一旦你弄清楚了你的设置对不同类型的调整的反应,就可以使用类似 loader.io 的东西来微调现实世界的性能。
您现在看到的性能表现有以下几点原因:
- 你可以通过添加 varnish 来增加每个连接的延迟(尝试直接点击 varnish)
- 你的 varnish 缓存命中率没有你预期的那么好,对于静态内容它应该是 100%(用来
varnishstat
找出答案) - 您缺少某些资源、打开文件描述符等。
- 如果您的服务速度为 7000 rps,但受到 10000 rps 的冲击,则有 3000 个请求未得到服务。这就是导致超时的原因。
- 日志记录实际上也会导致故障。对于 Varnish 来说,这应该不是问题(它使用共享内存和单独的进程),但我不知道如何在 HAProxy 和 nginx 中完成日志记录
- 我想我们会想出更多……