33 votes

Définition des valeurs server_names_hash_max_size et server_names_hash_bucket_size de Nginx

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

Redémarrage de nginx : nginx: [emerg] impossible de construire le serveur_names_hash, 
vous devriez augmenter server_names_hash_max_size: 256 
ou server_names_hash_bucket_size: 64.

Avec environ 200 domaines et en augmentation, nous avons dû augmenter la taille max du server_names_hash à 4112 et nous sommes préoccupés par le fait que cela ne va pas bien évoluer. Je cherche à comprendre comment ces configurations fonctionnent et quels paramètres optimaux devraient être définis pour nous permettre de passer à des milliers de domaines en utilisant cette méthode.

Aussi, à cette taille de hachage, nginx commence à mettre plusieurs secondes pour recharger, ce qui rend le système indisponible pendant son redémarrage.

Voici les paramètres globaux (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 {

    ##
    # Paramètres de base
    ##

    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;

    ##
    # Paramètres de journalisation
    ##

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

    ##
    # Paramètres de compression Gzip
    ##

    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;

    ##
    # Configurations des hôtes virtuels
    ##

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

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

(Ci-dessous se trouvent quelques configurations principales du site et un intercepteur)

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!!

40voto

lstg Points 29

Juste quelques détails techniques que j'ai trouvé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'abord max_size tant qu'il se plaint. Si le nombre dépasse un grand nombre (32769 par exemple), augmentez bucket_size en multiple de la valeur par défaut sur votre plateforme tant qu'il se plaint. S'il ne se plaint plus, diminuez max_size à nouveau tant qu'il ne se plaint pas. Maintenant, vous avez la meilleure configuration pour votre ensemble de noms de serveurs (chaque ensemble de noms de serveurs peut nécessiter une configuration différente).
  • Un max_size plus grand signifie une consommation de mémoire plus importante (une fois par travailleur ou serveur, merci de commenter si vous savez).
  • Un bucket_size plus grand signifie plus de cycles CPU (pour chaque recherche de nom de domaine) et plus de transferts de la mémoire principale au cache.
  • max_size n'est pas directement lié au nombre de noms de serveurs, si le nombre de serveurs double, vous devrez peut-être augmenter max_size 10 fois ou même plus pour éviter les collisions. Si vous ne pouvez pas les éviter, vous devrez augmenter bucket_size.
  • On dit qu'il faut augmenter bucket_size à la puissance de deux supérieure, d'après le code source je jugerais qu'il suffirait de le mettre en multiple de la valeur par défaut, cela devrait maintenir les transferts au cache optimaux.
  • Un nom de domaine moyen devrait tenir dans 32 octets même avec les frais généraux du tableau de hachage. Si vous augmentez bucket_size à 512 octets, cela pourrait accueillir 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 recherchera de manière linéaire. Vous voulez avoir le moins de collisions possible.
  • Si vous avez max_size inférieur à 10000 et un petit bucket_size, vous pourriez rencontrer des temps de chargement longs car nginx tenterait de trouver une taille de hachage optimale dans une boucle.
  • Si vous avez max_size supérieur à 10000, il y aura "seulement" 1000 boucles effectuées avant qu'il ne se plaigne.

20voto

Michael Hampton Points 232226

La liste des noms de serveur que nginx sert est stockée dans une table de hachage pour une recherche rapide. En augmentant le nombre d'entrées, vous devez augmenter la taille de la table de hachage et/ou le nombre de seaux de hachage dans la table.

Étant donné la nature de votre configuration, je ne vois aucun moyen de réduire facilement le nombre de noms de serveur que vous stockez dans la table. Je suggère cependant de ne pas "redémarrer" nginx, mais simplement de lui faire recharger sa configuration. Par exemple:

service nginx reload

5voto

Pedro Alvares Points 139

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

Je l'avais mis à 64 et je l'ai changé à 128.

Problème résolu.

3voto

TGO Points 121

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 produisait parce que j'incluais proxy_params, et il contient cette ligne entre autres :

proxy_set_header X-Forwarded-Proto $scheme;

En supprimant cette ligne de la configuration de mon site, l'avertissement a disparu.

2voto

Fleshgrinder Points 3558

@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 fonctionne très rapidement. Je suppose que cette table de hachage pourrait croître beaucoup plus sans dégrader les performances de manière notable. Mais je suggère d'utiliser une taille qui est une puissance de deux, comme 4096, en raison de la nature du code C.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X