Définition de Nginx server_names_hash_max_size et server_names_hash_bucket_size

22

Nous utilisons Nginx comme proxy inverse d'Apache dans un service qui donne à quiconque son propre site Web. Lors de la création du compte, le système crée un nouveau fichier de configuration nginx pour le domaine avec deux entrées, l'une pour le port 80, l'autre pour 443. Nous remarquons que tous les 30 domaines environ, nous obtenons l'erreur:

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.

Avec environ 200 domaines et en pleine croissance, nous avons dû augmenter la taille de server_names_hash_max à 4112 et craignons que cela ne se développe pas bien. Je cherche à comprendre comment ces configurations fonctionnent et quels seraient les paramètres optimaux pour garantir que nous pouvons atteindre des milliers de domaines en utilisant cette méthode.

De plus, à cette taille de hachage, nginx commence à prendre quelques secondes pour se recharger, ce qui rend le système indisponible pendant le redémarrage.

Voici les paramètres généraux (fonctionnant sur le serveur 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;
}

(Ci-dessous les chiffres sont quelques configurations de site principal et un fourre-tout):

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;
}

(Et un exemple de fichier de configuration utilisateur)

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;
}
}

Toute aide et direction est grandement appréciée !!

jasonspalace
la source

Réponses:

14

La liste des servernoms servis par nginx est stockée dans une table de hachage pour une recherche rapide . Lorsque vous augmentez le nombre d'entrées, vous devez augmenter la taille de la table de hachage et / ou le nombre de compartiments de hachage dans la table.

Compte tenu de la nature de votre configuration, je ne vois aucun moyen pour vous de réduire facilement le nombre de servernoms que vous stockez dans le tableau. Je suggérerai cependant de ne pas "redémarrer" nginx, mais plutôt de simplement le recharger sa configuration. Par exemple:

service nginx reload
Michael Hampton
la source
C'est très bien pour la dernière partie de la question, merci. Dois-je donc craindre que la valeur de server_names_hash_max_size soit d'environ 20000 pour accéder à 10000 domaines?
jasonspalace
Ce n'est qu'un problème lorsque vous redémarrez nginx. Comme je l'ai dit, reloadau lieu de cela chaque fois que possible pour éviter le problème.
Michael Hampton
23

Juste quelques détails techniques que j'ai creusés dans le code source:

  • La recommandation générale serait de garder les deux valeurs aussi petites que possible.
  • Si nginx se plaint, augmentez d' max_sizeabord tant qu'il se plaint. Si le nombre dépasse un grand nombre (32769 par exemple), augmentez bucket_sizeau multiple de la valeur par défaut sur votre plate-forme tant qu'il se plaint. S'il ne se plaint plus, diminuez à max_sizenouveau tant qu'il ne se plaint pas. Vous disposez maintenant de la meilleure configuration pour votre ensemble de noms de serveurs (chaque ensemble de noms_serveurs peut nécessiter une configuration différente).
  • Plus grand max_sizesignifie plus de mémoire consommée (une fois par travailleur ou serveur, veuillez commenter si vous le savez).
  • Plus grand bucket_sizesignifie plus de cycles CPU (pour chaque recherche de nom de domaine) et plus de transferts de la mémoire principale vers le cache.
  • max_sizen'est pas directement lié au nombre de server_names, si le nombre de serveurs double, vous devrez peut-être augmenter max_size10 fois ou même plus pour éviter les collisions. Si vous ne pouvez pas les éviter, vous devez augmenter bucket_size.
  • bucket_size est censé être augmenté à la puissance suivante de deux, à partir du code source, je dirais que cela devrait suffire à le rendre multiple de la valeur par défaut, cela devrait maintenir les transferts vers le cache optimal.
  • Le nom de domaine moyen doit tenir sur 32 octets même avec une surcharge de tableau de hachage. Si vous augmentez bucket_sizeà 512 octets, il accepterait 16 noms de domaine avec une clé de hachage en collision. Ce n'est pas quelque chose que vous voulez, si une collision se produit, elle recherche linéairement . Vous voulez avoir le moins de collisions possible.
  • Si vous en avez max_size moins de 10000 et petit bucket_size, vous pouvez rencontrer un temps de chargement long car nginx essaierait de trouver la taille de hachage optimale dans une boucle.
  • Si vous en avez max_sizeplus de 10000, il n'y aura "que" 1000 boucles effectuées avant qu'il ne se plaigne.
brablc
la source
Ce sont d'excellentes informations; merci pour la recherche et la rédaction.
womble
@brablc Je suis curieux de savoir comment vous êtes arrivé au 32769 par exemple. Où peut-on voir quelle est la taille actuelle du tas?
Uhl Hosting
La mémoire occupée serait max_size * bucket_size (mais je ne sais pas si elle est partagée ou par travailleur). J'avais 8000 noms de serveurs et 32769 me semblaient déjà trop élevés. Mais si vous avez beaucoup de mémoire, vous voudrez peut-être aller plus haut.
brablc
4

Augmentez la configuration "server_names_hash_bucket_size" dans votre nginx.conf.

Je l'ai eu 64 et changé à 128.

Problème résolu.

Pedro Alvares
la source
2

@Michael Hampton a absolument raison avec sa réponse. Cette table de hachage est construite et compilée lors du redémarrage ou du rechargement et ensuite elle s'exécute très rapidement. Je suppose que cette table de hachage pourrait augmenter beaucoup plus sans dégrader les performances notables. Mais je suggère d'utiliser une taille qui est une puissance de deux, comme 4096, en raison de la nature du code C.

Broyeur de chair
la source
Puissance de deux avec quelle base, est-il correct de croître par multiples de 512 par défaut?
jasonspalace
Oui absolument.
Fleshgrinder
1

Je ne suis pas sûr à 100% dans votre cas, mais je recevais le même avertissement parce que j'appelais proxy_set_header pour X-Forwarded-Proto deux fois:

proxy_set_header X-Forwarded-Proto ...;

Cela se passait parce que j'incluais proxy_params, et il contient cette ligne entre autres:

proxy_set_header X-Forwarded-Proto $scheme;

La suppression de cette ligne de la configuration de mon site a fait disparaître l'avertissement.

TGO
la source
1
vrais conseils $$$, merci.
SJA
-2

Changement

proxy_set_header X-Forwarded-For $remote_addr;

à

proxy_set_header X-Real-IP $remote_addr;

javi
la source