Impostazione Nginx nome_server_hash_max_size e nome_server_hash_bucket_size


22

Stiamo utilizzando Nginx come proxy inverso per Apache in un servizio che offre a chiunque il proprio sito Web. Al momento della creazione dell'account, il sistema crea un nuovo file conf nginx per il dominio con due voci, una per la porta 80, l'altra per 443. Stiamo notando che ogni 30 domini circa otteniamo l'errore:

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.

Con circa 200 domini e in crescita abbiamo dovuto aumentare la dimensione server_names_hash_max a 4112 e siamo preoccupati che questo non si ridimensioni bene. Sto cercando di capire come funzionano queste configurazioni e quali sarebbero le impostazioni ottimali per assicurarci di poter arrivare a migliaia di domini usando questo metodo.

Inoltre, a quella dimensione di hash, nginx sta iniziando a richiedere alcuni secondi per ricaricarsi, il che rende il sistema non disponibile mentre si riavvia.

Ecco le impostazioni generali (in esecuzione sul server 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;
}

(Sotto le cifre ci sono due configurazioni del sito principale e una cattura tutto):

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

(E un file di configurazione utente di esempio)

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

Qualsiasi aiuto e direzione è molto apprezzato !!

Risposte:


14

L'elenco dei servernomi serviti da nginx è memorizzato in una tabella hash per una rapida ricerca . Quando si aumenta il numero di voci, è necessario aumentare la dimensione della tabella hash e / o il numero di bucket hash nella tabella.

Data la natura della tua configurazione, non riesco a pensare ad alcun modo per ridurre facilmente il numero di servernomi che stai memorizzando nella tabella. Suggerirò, tuttavia, di non "riavviare" nginx, ma piuttosto di farlo ricaricare la sua configurazione. Per esempio:

service nginx reload

Questo è fantastico per l'ultima parte della domanda, grazie. Quindi dovrei essere preoccupato che server_names_hash_max_size sarà da qualche parte circa 20000 per arrivare a 10000 domini?
Jasonspalace,

È solo un problema quando riavvii nginx. Come ho già detto, reloadinvece , quando possibile, per evitare il problema.
Michael Hampton

23

Solo alcuni dettagli tecnici che ho scavato dal codice sorgente:

  • La raccomandazione generale sarebbe quella di mantenere entrambi i valori il più piccolo possibile.
  • Se nginx si lamenta, aumenta max_sizeprima di lamentarsi. Se il numero supera un numero grande (ad esempio 32769), aumenta bucket_sizea multiplo del valore predefinito sulla piattaforma fino a quando si lamenta. Se non si lamenta più, riduci max_sizefinché non si lamenta. Ora hai la migliore configurazione per il tuo set di nomi di server (ogni set di server_names potrebbe aver bisogno di una configurazione diversa).
  • Più grande max_sizesignifica più memoria consumata (una volta per lavoratore o server, si prega di commentare se lo si conosce).
  • Più grande bucket_sizesignifica più cicli di CPU (per ogni ricerca di nomi di dominio) e più trasferimenti dalla memoria principale alla cache.
  • max_sizenon è direttamente correlato al numero di nomi_server, se il numero di server raddoppia, potrebbe essere necessario aumentare di max_size10 volte o anche di più per evitare collisioni. Se non puoi evitarli, devi aumentare bucket_size.
  • bucket_size si dice che sia aumentato alla potenza successiva di due, dal codice sorgente ritengo che dovrebbe essere sufficiente per renderlo multiplo del valore predefinito, questo dovrebbe mantenere i trasferimenti nella cache ottimale.
  • Il nome di dominio medio dovrebbe contenere 32 byte anche con overhead dell'array di hash. Se aumenti bucket_sizea 512 byte, ospiterebbe 16 nomi di dominio con chiave hash in collisione. Questo non è qualcosa che desideri, se si verifica una collisione cerca in modo lineare . Vuoi avere il minor numero possibile di collisioni.
  • Se hai max_size meno di 10000 e piccoli bucket_size, puoi imbatterti in lunghi tempi di caricamento perché nginx cercherebbe di trovare la dimensione hash ottimale in un ciclo.
  • Se hai max_sizepiù di 10000, ci saranno "solo" 1000 loop eseguiti prima che si lamentino.

Questa è un'ottima informazione; grazie per la ricerca e la redazione.
womble

@brablc Sono curioso di sapere come sei arrivato a 32769 per esempio. Dove si può vedere qual è l'attuale dimensione dell'heap?
Uhl Hosting

La memoria occupata sarebbe max_size * bucket_size (ma non so se sia condivisa o per lavoratore). Avevo 8000 nomi di server e 32769 erano già troppo alti. Ma se hai un sacco di memoria, potresti voler andare più in alto.
brablc

4

Aumenta la configurazione "server_names_hash_bucket_size" all'interno di nginx.conf.

L'ho avuto 64 e cambiato in 128.

Problema risolto.


2

@Michael Hampton ha assolutamente ragione con la sua risposta. Questa tabella hash viene costruita e compilata durante il riavvio o il ricaricamento e successivamente viene eseguita molto velocemente. Immagino che questa tabella di hash potrebbe crescere molto di più senza degradare le prestazioni evidenti. Ma suggerirei di usare una dimensione che è potenza di due, come 4096, a causa della natura del codice C.


Potenza di due con quale base, è corretto crescere in multipli del valore predefinito di 512?
Jasonspalace,

Si assolutamente.
Fleshgrinder,

1

Non sono sicuro al 100% nel tuo caso, ma stavo ricevendo lo stesso avviso perché stavo chiamando due volte proxy_set_header per X-Forwarded-Proto:

proxy_set_header X-Forwarded-Proto ...;

Questo stava accadendo perché includevo proxy_params e contiene questa riga tra le altre:

proxy_set_header X-Forwarded-Proto $scheme;

La rimozione di quella linea dalla configurazione del mio sito ha fatto scomparire l'avviso.


1
vero consiglio di $$$, grazie.
sabato

-2

Modificare

proxy_set_header X-Forwarded-For $remote_addr;

per

proxy_set_header X-Real-IP $remote_addr;

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.