Das Neuladen von Nginx schlägt stillschweigend fehl (98: Adresse bereits in Verwendung), aber nichts anderes lauscht auf dem Port

Das Neuladen von Nginx schlägt stillschweigend fehl (98: Adresse bereits in Verwendung), aber nichts anderes lauscht auf dem Port

Ich versuche das jetzt seit fast 6 Monaten herauszufinden. Das Problem tritt zufällig auf, unabhängig von der Nginx- oder Ubuntu-Version. Das nginx-extras-Paket wird aus den Ubuntu-Repositorys verwendet. Dies ist eine Gruppe von 10 Servern mit unterschiedlicher Hardware, die dasselbe Problem haben.

Kurz gesagt: Nginx kann gelegentlich nicht neu geladen werden. Das Fehlerprotokoll zeigt an, dass keine Bindung an die Adresse hergestellt werden konnte (aktuell passiert das für Port 443, aber es passiert auch gelegentlich für Port 80). Manchmal service nginx upgradewird der Server durch das Ausführen von neu geladen. Wenn das auch fehlschlägt, service nginx restartfunktioniert es manchmal und manchmal nicht. Wenn selbst dies fehlschlägt, besteht die einzige Möglichkeit, die Konfiguration neu zu laden, darin, auszuführen service nginx stop, einige Sekunden zu warten und dann auszuführen service nginx start. Keiner dieser Befehle gibt jemals einen Fehler zurück, sondern sie werden zurückgegeben, [OK]selbst wenn der Befehl fehlschlägt.

Das Anhalten und Starten von Nginx ist ein Problem, da diese Maschinen große Dateien senden und die Übertragungen unterbrochen werden. Wenn außerdem eine große Datei zum Zwischenspeichern aus dem Backend abgerufen wird, wird die zwischengespeicherte Version beim Neustart beschädigt.

nginx version: nginx/1.4.6 (Ubuntu)
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) 
TLS SNI support enabled
configure arguments: 
--with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' 
--prefix=/usr/share/nginx 
--conf-path=/etc/nginx/nginx.conf 
--http-log-path=/var/log/nginx/access.log 
--error-log-path=/var/log/nginx/error.log 
--lock-path=/var/lock/nginx.lock 
--pid-path=/run/nginx.pid 
--http-client-body-temp-path=/var/lib/nginx/body 
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi 
--http-proxy-temp-path=/var/lib/nginx/proxy 
--http-scgi-temp-path=/var/lib/nginx/scgi 
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi 
--with-debug 
--with-pcre-jit 
--with-ipv6 
--with-http_ssl_module 
--with-http_stub_status_module 
--with-http_realip_module 
--with-http_addition_module 
--with-http_dav_module 
--with-http_flv_module 
--with-http_geoip_module 
--with-http_gzip_static_module 
--with-http_image_filter_module 
--with-http_mp4_module 
--with-http_perl_module 
--with-http_random_index_module 
--with-http_secure_link_module 
--with-http_spdy_module 
--with-http_sub_module 
--with-http_xslt_module 
--with-mail 
--with-mail_ssl_module 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/headers-more-nginx-module 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-auth-pam
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-cache-purge 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-dav-ext-module 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-development-kit 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-echo 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/ngx-fancyindex 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-http-push 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-lua 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-upload-progress 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/nginx-upstream-fair 
--add-module=/build/nginx-hzyca8/nginx-1.4.6/debian/modules/ngx_http_substitutions_filter_module

Aktuell laufender Prozess:

# ps ax | grep nginx
25771 pts/1    S+     0:00 grep --color=auto nginx
29145 ?        S      0:00 nginx: master process /usr/sbin/nginx
29664 ?        RN   516:47 nginx: worker process
29665 ?        SN   513:46 nginx: worker process
29666 ?        SN   514:17 nginx: worker process
29667 ?        SN   517:24 nginx: worker process
29668 ?        SN   512:29 nginx: worker process
29669 ?        SN   515:28 nginx: worker process
29670 ?        SN   517:52 nginx: worker process
29671 ?        SN   507:52 nginx: worker process
29672 ?        S      0:13 nginx: cache manager process

Neuladeversuch:

# service nginx reload
 * Reloading nginx configuration nginx   [ OK ]

Wenn ich mir die PS-Ausgabe noch einmal anschaue, ist nichts passiert:

# ps ax | grep nginx
29145 ?        S      0:00 nginx: master process /usr/sbin/nginx
29664 ?        SN   516:54 nginx: worker process
29665 ?        SN   513:49 nginx: worker process
29666 ?        SN   514:20 nginx: worker process
29667 ?        SN   517:27 nginx: worker process
29668 ?        SN   512:34 nginx: worker process
29669 ?        SN   515:31 nginx: worker process
29670 ?        SN   518:08 nginx: worker process
29671 ?        SN   507:55 nginx: worker process
29672 ?        S      0:13 nginx: cache manager process
31121 pts/1    S+     0:00 grep --color=auto nginx

Eine Kontrolle im Fehlerprotokoll (IP-Adresse geschwärzt):

2018/03/10 00:22:29 [info] 32481#0: Using 32768KiB of shared memory for push module in /etc/nginx/nginx.conf:95
2018/03/10 00:22:29 [emerg] 29145#0: bind() to 195.181.160.xx:443 failed (98: Address already in use)
2018/03/10 00:22:29 [emerg] 29145#0: bind() to 195.181.160.xx:443 failed (98: Address already in use)
2018/03/10 00:22:29 [emerg] 29145#0: bind() to 195.181.160.xx:443 failed (98: Address already in use)
2018/03/10 00:22:29 [emerg] 29145#0: bind() to 195.181.160.xx:443 failed (98: Address already in use)
2018/03/10 00:22:29 [emerg] 29145#0: bind() to 195.181.160.xx:443 failed (98: Address already in use)
2018/03/10 00:22:29 [emerg] 29145#0: still could not bind()

Der einzige Prozess, der 443 verwendet, ist nginx selbst:

# sudo netstat -tulpn | grep :443
tcp        0      0 0.0.0.0:443     0.0.0.0:*      LISTEN      29145/nginx

Auf diesen Servern hat jeder Kunde zwei Serverblöcke - einen öffentlichen, der auf Standardports lauscht, und einen internen, der das Caching übernimmt. Letzterer lauscht auf einer lokalen IP-Adresse auf einem eindeutigen Port und wird über Proxy_Pass vom öffentlichen Block aus aufgerufen. Diese internen Blöcke leiten alle selbst Proxy_Pass an andere Standorte weiter. Die Gründe für diese Konfiguration sind zu komplex, um sie hier zu erläutern.

Was habe ich bisher überprüft:

  • Alle internen Blöcke können ihre Upstreams auflösen

  • Alle internen Ports sind eindeutig und werden nicht von anderen Diensten verwendet.

  • SPDY wird nicht verwendet (ein Fehler wurde auf der Mailingliste von Nginx gemeldet)

  • Das Problem tritt zufällig auf, tritt aber wahrscheinlicher auf, je länger eine Nginx-Instanz ausgeführt wird.

  • Verhalten sowohl in Ubuntu 14.04.X als auch 16.04, Nginx-Versionen 1.4.6 bis aktuell vorhanden.

  • Kein offensichtlicher Zusammenhang mit CPU-, Festplatten- oder Netzwerklast

Beispiel-Serverblöcke, wie sie automatisch von der Plattform generiert werden, die diese Server verwendet (einige Informationen redigiert):

Öffentlicher Block:

server {

    keepalive_timeout 10;

    listen 195.xx.xx.xx:80;
    #listen 195.xx.xx.xx:80 ssl;
    root /home/nginx;  
    server_name xxxxxx.xxxxxx.com ;

    index index.php index.html index.htm index.nginx-debian.html

    error_page 403 /403.html; location = /403.html {
        return https://www.xxxxxx.com/403.php;
    }

    error_page 404 /404.html; location = /404.html {
        return https://www.xxxxxx.com/404.php;
    }

    error_page 500 /500.html; location = /500.html {
        root /home/nginx;
    }

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        return 301 http://xxxxx.xxxxxxx.com$request_uri;
    }

    location / {

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        geo_xxxxx     $geoip_country_code;
        proxy_intercept_errors  on;

        proxy_buffering        off;
        proxy_pass             http://127.0.1.3:8213;

        set $sent_http_accept_ranges bytes;

    } 

    location ~ /playlist.m3u8 {              

        secure_link $arg_st,$arg_e;
        secure_link_md5 xxxxxxxxxxxxxxxxxxxx$uri$remote_addr$arg_e;

        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header        geo_xxxxxx     $geoip_country_code;
            proxy_intercept_errors  on;

            proxy_buffering        off;
            proxy_pass             http://127.0.1.3:8213;
    } 


    #ssl_certificate /etc/letsencrypt/live//fullchain.pem; # managed by Certbot
    #ssl_certificate_key /etc/letsencrypt/live//privkey.pem; # managed by Certbot
    #include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    limit_rate 10000k;

} 

Zugehöriger privater Block:

proxy_cache_path  /home/nginx/282-281-cache levels=1:2 
keys_zone=282-281:5m inactive=48h  max_size=500g;
limit_conn_zone $http_x_forwarded_for zone=addr282-281:10m;    

map $http_user_agent $blockedUA {
default 0;
"~thisisadummyua" 1;
"~thisisanotherdummyua" 1;
} 

map $http_referer $blockedREF {
default 0;
"~thisisadummyref.com" 1;
"~thisisanotherdummyref.com" 1;
}     

server { 

    limit_conn addr282-281 100;
    limit_conn_status 429;

    keepalive_timeout 10;

    listen 127.0.1.3:8213;
    root /home/nginx;  
    server_name 127.0.1.3;   

    location ~* \.(m3u8)$ {
            real_ip_header X-Forwarded-For;
            set_real_ip_from xxx.xx.xx.xx/xx;
            proxy_set_header        geo_xxxxx     $geoip_country_code;
            proxy_set_header       Host $proxy_host;
            real_ip_recursive on;

            # CORS setup
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Expose-Headers' 'Content-Length';

            proxy_ignore_headers Cache-Control;
            add_header Cache-Control public;

            # allow CORS preflight requests
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            add_header Edge-Cache $upstream_cache_status; 
            proxy_cache            282-281;

            proxy_cache_valid      200 206 5s;
            proxy_cache_use_stale  error timeout invalid_header updating
                                   http_500 http_502 http_503 http_504;
            proxy_cache_lock       on;
            proxy_cache_lock_timeout 10s;
            proxy_cache_key        $uri;
            proxy_pass http://xxx.xx.xx.xx:41000;
    }

    location / {
            deny 10.10.10.1;
            deny 10.10.10.2;

            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Expose-Headers' 'Content-Length';

            proxy_ignore_headers X-Accel-Expires Expires Cache-Control; 
            proxy_ignore_headers Set-Cookie; 
            add_header Cache-Control public;

            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }

            real_ip_header X-Forwarded-For;
            set_real_ip_from xxx.xx.xx.xx/xx;
            proxy_set_header        geo_xxxxx     $geoip_country_code;
            proxy_set_header       Host $proxy_host;

            proxy_http_version 1.1;
            real_ip_recursive on;
            proxy_set_header Range $http_range;
            proxy_set_header If-Range $http_if_range;
            proxy_no_cache $http_range $http_if_range;    
            proxy_cache_bypass $http_range $http_if_range;
            proxy_temp_path        /home/nginx/282-281-temp;
            proxy_buffering        on;
            proxy_max_temp_file_size 25m;
            proxy_intercept_errors  on;

            proxy_cache_purge PURGE from all; 

            add_header Edge-Cache $upstream_cache_status; 
            proxy_cache            282-281;

            proxy_cache_valid      200 206 5m;
            proxy_cache_use_stale  error timeout invalid_header updating
                                   http_500 http_502 http_503 http_504;
            proxy_cache_lock       on;
            proxy_cache_lock_timeout 120s;
            proxy_cache_key        $uri;
            proxy_pass             http://xxx.xx.xx.xx:41000/;


    }

    if ($blockedUA = 1){
        return https://www.xxxxxxx.com/403.php;
    }    

    #if ($http_user_agent = "") { 
    #     return https://www.xxxxxxx.com/403.php;
    #}

    if ($blockedREF = 1){
        return https://www.xxxxxxx.com/403.php;
    }  

    access_log /var/log/nginx/xxxx/xxx-xxx-proxy-access.log xxxx;
    error_log /var/log/nginx/xxxx/xxx-xxx-proxy-error.log;


}`

Ich überlege jetzt, das nginx-common-Paket auszuprobieren, aber das sind Produktionssysteme. Ich bin nicht sicher, ob das Problem auf einer Testmaschine auftreten würde.

BEARBEITEN: Nachdem ich diese Frage gestellt hatte, habe ich beschlossen, einen Cron-Job hinzuzufügen, der alle 3 Stunden neu lädt, da ich beobachtet habe, dass das Problem umso wahrscheinlicher auftritt, je länger Nginx ohne Neuladen läuft. Heute ist der Cron-Job nun schon den dritten Tag aktiv und alle Server reagieren korrekt auf Neuladungen, und das Problem ist bisher bei keinem von ihnen aufgetreten. Bestenfalls ist das nichts weiter als ein Pflaster und löst das eigentliche Problem nicht. Es ist jedoch das Beste, was mir eingefallen ist, und so ziemlich das Einzige, was zu funktionieren scheint.

EDIT2: Das Hinzufügen eines Crons hat das Problem nicht behoben, aber ich musste es versuchen. Ich habe dann Nginx aus dem Quellcode mit der geringstmöglichen Anzahl von Modulen kompiliert, mit denen wir arbeiten können, und es auf einem der Server installiert. Das war vor 7 Tagen und dieser eine Server hatte das Problem seitdem nicht mehr. Da ich unter Zeitdruck stehe, habe ich vor 3 Tagen beschlossen, nicht länger zu warten und habe begonnen, die Produktionsserver nacheinander herunterzufahren, um ihr Nginx durch die neu kompilierte Version zu ersetzen. Bisher so gut und keiner von ihnen zeigt mehr Anzeichen des Problems. Hoffen wir, dass ich nicht für eine dritte Bearbeitung zurückkomme.

Antwort1

Das passiert von Zeit zu Zeit. Es ist also nichts Besonderes.

Wenn wir unsere Dienste neu starten oder neu laden möchten, haben wir folgende Vorgehensweise festgelegt:

1. Überprüfen Sie, ob die Konfiguration wie erwartet funktioniert:

nginx -t

2. Starten Sie Nginx neu und überprüfen Sie die Antwort:

service nginx restart

3. Wenn der Neustart aufgrund einer Portkollision nicht möglich war ...

Prüfen Sie, welcher Dienst den Port blockiert:

netstat -nltp | grep -E ':80\W|:443\W'

Entsprechenden Dienst beenden:

killall nginx

In manchen Fällen kann ein Prozess eingefroren sein. Sie müssen den hängenden Prozess mit mehr Kraft beenden:

kill -9 {process_id}

verwandte Informationen