如何在我的网络服务器上实现每秒 50 万个请求?

Arp*_*mbi 8 performance nginx scalability web-server performance-tuning

我最近给自己赠送了一台新的专用服务器,我正试图从中榨取最大的性能,以获得乐趣和学习。

我正在尝试实现该服务器每秒可以处理的最大可能请求数,目标是 500K 请求/秒,如此处所述 - http://lowlatencyweb.wordpress.com/2012/03/20/500000-requestssec-modern-http-servers -很快/

服务器详情

英特尔® 至强® E3-1270 4 核 (8 HT) x 3.4 GHz

内存 24 GB DDR3 ECC

硬盘空间 2,000 GB (2 x 2,000 SATA) RAID 软件 RAID 1

局域网 100mbps

操作系统 Centos 6.3 64 位

nginx

对于静态 txt 文件,我只能达到 35K 请求/秒。我在同一台机器上运行基准测试。我知道 NIC 限制和网络开销

ab -n100000 -c200 http://localhost/test.txt
Run Code Online (Sandbox Code Playgroud)

更新- 165K 请求/秒

我尝试了另一个名为的基准测试工具wrk,它给了我 165K 请求/秒。非常酷!

更新 2 - 250K 请求/秒

配置文件

#######################################################################
#
# This is the main Nginx configuration file.
#
# More information about the configuration options is available on
#   * the English wiki - http://wiki.nginx.org/Main
#   * the Russian documentation - http://sysoev.ru/nginx/
#
#######################################################################

#----------------------------------------------------------------------
# Main Module - directives that cover basic functionality
#
#   http://wiki.nginx.org/NginxHttpMainModule
#
#----------------------------------------------------------------------

user              nginx;
worker_processes  8;
worker_rlimit_nofile 262144;

error_log  /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;

pid        /var/run/nginx.pid;


#----------------------------------------------------------------------
# Events Module
#
#   http://wiki.nginx.org/NginxHttpEventsModule
#
#----------------------------------------------------------------------

events {
    worker_connections  16384;
    multi_accept on;
    use epoll;
}


#----------------------------------------------------------------------
# HTTP Core Module
#
#   http://wiki.nginx.org/NginxHttpCoreModule
#
#----------------------------------------------------------------------

http {
    include       /etc/nginx/mime.types;
    index    index.php index.html index.htm;

    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay on;
    server_tokens off;
    client_max_body_size 24m;
    client_body_buffer_size 128k;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    open_file_cache max=1000;
    open_file_cache_min_uses 10;
    open_file_cache_errors   on;

    gzip on;
        gzip_static on;
    gzip_comp_level 3;
    gzip_disable "MSIE [1-6]\.";
        gzip_http_version 1.1;
        gzip_vary on;
        gzip_proxied any;
        gzip_types text/plain text/css text/xml text/javascript text/x-component text/cache-manifest application/json application/javascript application/x-javascript application/xml application/rss+xml application/xml+rss application/xhtml+xml application/atom+xml application/wlwmanifest+xml application/x-font-ttf image/svg+xml image/x-icon font/opentype app/vnd.ms-fontobject;
        gzip_min_length  1000;

fastcgi_cache_path   /tmp  levels=1:2
                       keys_zone=NAME:10m
                       inactive=5m;

  fastcgi_cache_key "$scheme$request_method$host$request_uri";


server {
    listen       80;
    server_name  _;
        root /var/www/html;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    error_page  404              /404.html;
    location = /404.html {
        root   /var/www/error;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /var/www/error;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
    # checks to see if the visitor is logged in, a commenter,
    # or some other user who should bypass cache
    set $nocache "";
    if ($http_cookie ~ (comment_author_.*|wordpress_logged_in.*|wp-postpass_.*)) {
     set $nocache "Y";
   }
    # bypass cache if logged in.
    # Be sure that this is above all other fastcgi_cache directives
    fastcgi_no_cache $nocache;
    fastcgi_cache_bypass $nocache;

  fastcgi_cache   NAME;
  fastcgi_cache_valid   200 302  10m;
  fastcgi_cache_valid   301      1h;
  fastcgi_cache_valid   any      1m;
  fastcgi_cache_min_uses  10;
  fastcgi_cache_use_stale error  timeout invalid_header http_500;
    fastcgi_buffers 256 16k;
    }

location = /favicon.ico {
        log_not_found off;
        access_log off;
}

location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
}

# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
}

# Deny access to any files with a .php extension in the uploads directory
location ~* ^/wp-content/uploads/.*.php$ {
        deny all;
        access_log off;
        log_not_found off;
}

location ~* \.(jpg|jpeg|gif|png|flv|mp3|mpg|mpeg|js|css|ico)$ {
        expires                 max;
        log_not_found   off;
}
}

}
Run Code Online (Sandbox Code Playgroud)

Cho*_*er3 32

Arpit,如果您想象绝对最小的 Web 响应,即使它是静态文本文件也是一个以太网数据包(约 1,500 字节),那么其中的 500,000 个大约为 750,000,000 字节,或大约 7.5 吉比特。因此,除非您的服务器非常轻松地卸载了 10Gb 网卡(事实并非如此,您所拥有的网卡速度要慢一百倍)并且已设置驱动程序和内核以允许您几乎完全淹没其中一个链接,加上负载平衡器、防火墙、路由器和以该速率的转发连接的延迟,那么您将永远无法达到这种性能——即使是单个数据包响应,这也是不太可能的。所以最终 35k 听起来离你的极限不远了。

  • @ArpitTambi [`你应该只根据你面临的实际问题提出实用的、可回答的问题`](http://serverfault.com/faq#dontask) <- 问题的一部分是实用的,它与*现实生活有关用例* - 有很多方法可以让 Web 服务器运行得非常快。他们中的许多人在现实世界中破裂(或变得非常脆弱),而您可能已接近您的实际极限。除了寻找和杀死明显的瓶颈(参见杰夫·弗兰德的回答),Chopper3 正在 *如实说*-有时正确的答案不是您想听到的。 (6认同)
  • @ArpitTambi:我建议阅读 Chopper 的回答。你的耐心将得到回报。 (4认同)
  • “端口冲突” - 1GbE 和更快的速度不会发生冲突,它的设计是完全双向的。 (3认同)
  • ? 我用单个 ZXTM NIC 实现了 10Gb (2认同)
  • @ScottPack 该答案非常适合现实生活中的用例,我正在同一台机器上进行测试,因此瓶颈不可能是网络。它是 CPU、内存或 IO。 (2认同)

VBa*_*art 13

首先,您应该编写一个新的基准测试工具。你实际上ab不是在进行基准测试nginx

  • 正确的。我尝试了 `wrk`,它给了我 165K 请求/秒。 (2认同)

Jef*_*and 8

让我们找出瓶颈。由于您在同一台机器上,我们可以假设它是 CPU 或磁盘活动。对于一个文本文件,它不应该是磁盘活动,但是在 35k 连接时,您每秒也可能生成 35MB 的日志记录。

您展示的示例不运行访问日志记录,只运行错误。但是,您的配置还有更多内容,尤其是日志记录:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

access_log  /var/log/nginx/access.log  main;
Run Code Online (Sandbox Code Playgroud)

从禁用该日志记录开始,然后找出下一步要挂断的地方。还要考虑在同一台机器上运行测试客户端会对服务器守护进程产生显着影响。Hypertheading 有时也可能有害,因此请探索它在打开或关闭时是否更适合您的负载。