Nginx 设置 server_names_hash_max_size 和 server_names_hash_bucket_size

Nginx 设置 server_names_hash_max_size 和 server_names_hash_bucket_size

我们正在使用 Nginx 作为 Apache 的反向代理,该服务可让任何人拥有自己的网站。在创建帐户时,系统会为域创建一个新的 nginx conf 文件,其中包含两个条目,一个用于端口 80,另一个用于 443。我们注意到,每 30 个左右的域都会收到错误:

Restarting nginx: nginx: [emerg] could not build the server_names_hash, 
you should increase either server_names_hash_max_size: 256 
or server_names_hash_bucket_size: 64.

由于域名数量约为 200 个且还在不断增长,我们不得不将 server_names_hash_max 大小增加到 4112,并且担心这不会很好地扩展。我希望了解这些配置的工作原理以及最佳设置是什么,以确保我们能够使用此方法扩展到数千个域名。

此外,在该哈希大小下,nginx 开始需要几秒钟才能重新加载,这导致系统在重新启动时不可用。

以下是整体设置(在 Ubuntu 服务器 10.10 nginx/1.0.4 上运行):

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events {
    worker_connections 4096;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 300;
    types_hash_max_size 2048;
    # server_tokens off;

    server_names_hash_bucket_size 64;
    # server_name_in_redirect off;
    # server_names_hash_max_size 2056;
    server_names_hash_max_size 4112;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    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/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;

ssl_session_cache shared:SSL:10m;
ssl_ciphers ALL:!kEDH:-ADH:+HIGH:+MEDIUM:-LOW:+SSLv2:-EXP;
}

(密码下方是几个主要站点配置和一个全部捕获):

include /etc/user-nginx-confs/*;

server {
listen 80;
server_name .domain.com;
location / {
proxy_pass http://127.0.0.1:8011;
proxy_set_header host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-SystemUse-Header 111;
}
}

server {
listen 443 ssl;
server_name .suredone.com;
ssl_certificate /etc/apache2/sddbx/sdssl/suredone_chained.crt;
ssl_certificate_key /etc/apache2/sddbx/sdssl/suredone.key;
location / {
proxy_pass http://127.0.0.1:44311;
proxy_set_header host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-SystemUse-Header 111;
}
}

server {
listen 80 default_server;
listen 443 default_server ssl;
server_name _;
ssl_certificate /ssl/site_chained.crt;
ssl_certificate_key /ssl/site.key;
return 444;
}

(以及示例用户配置文件)

server {
listen 80;
server_name username.domain.com;
location / {
proxy_pass http://127.0.0.1:8011;
proxy_set_header host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-SystemUse-Header 1111;
}
}

server {
listen 443 ssl;
server_name username.domain.com;
ssl_certificate /ssl/site_chained.crt;
ssl_certificate_key /ssl/site.key;
location / {
proxy_pass http://127.0.0.1:44311;
proxy_set_header host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-SystemUse-Header 1111;
}
}

非常感谢任何帮助和指导!!

答案1

servernginx 服务的名称列表是存储在哈希表中以便快速查找随着条目数量的增加,您必须增加哈希表的大小和/或表中哈希桶的数量。

鉴于您的设置性质,我想不出任何方法可以轻松减少server表中存储的名称数量。不过,我建议您不要“重新启动”nginx,而是让它重新加载配置。例如:

service nginx reload

答案2

以下是我从源代码中挖掘出的一些技术细节:

  • 一般建议是使这两个值尽可能保持较小。
  • 如果 nginx 抱怨,max_size则先增加,直到它抱怨为止。如果数字超过某个大数字(例如 32769),则增加到bucket_size您平台上默认值的倍数,直到它抱怨为止。如果它不再抱怨,则减少,max_size直到它不再抱怨为止。现在,您已经为服务器名称集做好了最佳设置(每组 server_names 可能需要不同的设置)。
  • 越大max_size意味着消耗的内存越多(每个工作者或服务器一次,如果您知道请评论)。
  • 更大bucket_size意味着更多的 CPU 周期(对于每个域名查找)和更多的从主内存到缓存的传输。
  • max_size与 server_names 的数量没有直接关系,如果服务器数量增加一倍,则可能需要增加max_size10 倍甚至更多以避免冲突。如果无法避免,则必须增加bucket_size
  • bucket_size据说会增加到下一个 2 的幂,从源代码来看,我判断它应该足以使其成为默认值的倍数,这应该可以使传输到缓存达到最佳状态。
  • 即使有哈希数组开销,平均域名也应该适合 32 个字节。如果增加到bucket_size512 个字节,它将容纳 16 个具有冲突哈希键的域名。如果发生冲突,这不是您想要的它线性搜索. 您希望尽可能减少碰撞。
  • 如果你有max_size 少于 10000并且很小bucket_size,您可能会遇到较长的加载时间,因为 nginx 会尝试在循环中找到最佳哈希大小。
  • 如果有max_size大于 10000 的数字,那么在出现抱怨之前“仅”会执行 1000 次循环。

答案3

增加 nginx.conf 中的“server_names_hash_bucket_size”配置。

我原来是 64,现在改成 128。

问题解决了。

答案4

@Michael Hampton 的回答完全正确。这个哈希表是在重启或重新加载期间构建和编译的,之后运行速度非常快。我猜这个哈希表可以增长很多而不会明显降低性能。但由于 C 代码的性质,我建议使用 2 的幂,例如 4096。

相关内容