Nginx 应该很快 —— 至少人们这么说。
我无法让 nginx 运行得更快。为了进行基准测试,我使用siege
多种配置来模拟高负载。因此,我尝试对单个服务器进行负载平衡(我知道对单个服务器进行负载平衡是相当无用的,但对于测试负载平衡器本身来说,这是有效的)。我已经设置了一个已经优化的 apache 反向代理作为参考。当我尝试从同一个后端服务器获取相同的(非缓存)文件时,我通过 nginx 获得大约 80tps,使用 apache 获得大约 350tps。当然,硬件/操作系统是相同的(当前双核 CPU、2G 内存、Ubuntu Server 16.04)。
我已经尝试更改工作程序、最大连接数、轮询方法、代理缓冲区大小、等待时间和客户端缓冲区。我可以看到系统负载很低,一个 nginx 使用大约 1% 的 CPU,连接将等待大约 5 到 6 秒。因为我想测量反向代理的性能,所以我不想在这个测试中缓存任何东西。
那么问题是:如何优化 nginx 作为非缓存反向代理的性能?
攻城命令示例:siege -c 100 -b -r 100 -v <loadbalancer>/favicon.ico
更新:根据要求进行一些配置。为了使问题符合 serverfault 的要求,请回答有关参数的一般有用信息。
user www-data;
worker_processes 2;
pid /run/nginx.pid;
#thread_pool default threads=1500 max_queue=65536;
worker_rlimit_nofile 40000;
events {
worker_connections 768;
#multi_accept on;
#use epoll;
}
http {
#aio threads=default;
#proxy_buffers 32 4m;
#proxy_busy_buffers_size 25m;
#proxy_buffer_size 512k;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
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 combined buffer=1k;
error_log /var/log/nginx/error.log;
gzip off;
# gzip_disable "msie6";
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
upstream kronos-backend {
server kronos.example.com;
}
server {
listen 80;
listen [::]:80;
ssl_certificate /etc/ssl/certs/snakeoil.crt;
ssl_certificate_key /etc/ssl/private/snakeoil.key;
listen 443 ssl;
listen [::]:443 ssl;
keepalive_timeout 60;
root /var/www/vhosts/default;
index index.html;
server_name <name>;
server_tokens off; # Don't show that nginx is bringing out the website.
location / {
proxy_set_header Host <name>;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://kronos-backend;
client_body_buffer_size 1M; # Lets keep all client-sent bodies in memory if less than 1 Megabyte. (Default for amd64: 16K)
client_max_body_size 10M; # Maximum accepted body is 10M (Default is 1M).
}
}
}
我知道这个配置不太干净。但它或多或少显示了我已经尝试过的内容。它源自 Ubuntu 中 nginx 包的默认配置。
连接方式如下:
+--- apache2 ---+
| |
siege -+ +--> some webserver (not of interest)
| |
+--- nginx -----+
因此,只要不涉及缓存,并且使用相同的 URL(在本例中为静态文件)进行测试,通过 nginx 或 apache2 传输的数据就无关紧要。任何 Web 服务器都没有故意激活缓存机制。
apache 中的配置使用 mpm_worker。
ThreadLimit 600
StartServers 4
ServerLimit 11
MinSpareThreads 50
MaxSpareThreads 100
ThreadsPerChild 200
MaxClients 1000
MaxRequestsPerChild 20000
上述围攻命令的示例输出:
$ siege -c 100 -b -r 10 <nginx>/wrapper_2_bg.png
** SIEGE 3.0.5
** Preparing 100 concurrent users for battle.
The server is now under siege.. done.
Transactions: 1000 hits
Availability: 100.00 %
Elapsed time: 11.01 secs
Data transferred: 0.12 MB
Response time: 0.84 secs
Transaction rate: 90.83 trans/sec
Throughput: 0.01 MB/sec
Concurrency: 76.24
Successful transactions: 1000
Failed transactions: 0
Longest transaction: 6.67
Shortest transaction: 0.03
$ siege -c 100 -b -r 10 <apache>/wrapper_2_bg.png
** SIEGE 3.0.5
** Preparing 100 concurrent users for battle.
The server is now under siege.. done.
Transactions: 1000 hits
Availability: 100.00 %
Elapsed time: 3.16 secs
Data transferred: 0.12 MB
Response time: 0.22 secs
Transaction rate: 316.46 trans/sec
Throughput: 0.04 MB/sec
Concurrency: 68.95
Successful transactions: 1000
Failed transactions: 0
Longest transaction: 3.06
Shortest transaction: 0.05
答案1
数据包丢失是问题的根源。负载均衡器和后端 Web 服务器之间有一个路由器。路由器似乎不够快,因为在测试时其负载达到 100%。结果就是数据包丢失。
我不知道为什么 apache 似乎能更好地处理这个问题。将负载平衡器移动到与交付 Web 服务器相同的网络,两种方式的性能几乎相同,而且要高得多。