doppelte Uploads
Seit wir von einer einfachen Apache-Instanz zu einer Umgebung mit Lastenausgleich gewechselt sind, treten manchmal Probleme mit wiederholten POST-Anforderungen auf. Wir führen Nginx als Reverse Proxy aus. Statischer Inhalt wird von Nginx selbst bereitgestellt, und dynamischer Inhalt wird von zwei Apache-Backends bereitgestellt.
Ich habe überprüft, dass es sich nicht um einen Schnittstellen- / Benutzerfehler handelt. Ein kleines Beispiel: Ein einfacher Bild-Upload führt dazu, dass das Bild zweimal hochgeladen wird. Die Anfrage / der POST wird nicht zweimal durch Doppelklick oder Benutzerfehler gesendet. Ich habe keine Beweise dafür gefunden, dass der Browser die Anfrage zweimal sendet, daher liegt mein Verdacht auf der Serverseite. (Beachten Sie, dass dies nur ein Verdacht ist.) Die meisten dieser Anfragen sind intern, dh sie stammen von Mitarbeitern, sodass ich überprüfen kann, wie sie zustande kommen.
Das einzige, was ich falsch finden kann, ist, dass nginx 499
in diesen Fällen einen Fehler protokolliert . Ich bin mir jedoch nicht sicher, ob dies die Ursache oder nur eine (Neben-) Wirkung des Problems ist. (Mir ist bekannt, dass 499 kein Standard-http-Status ist, sondern ein Nginx-Status, der bedeutet, dass der Client die Verbindung geschlossen hat.)
Anfragen
Die wiederholten POST-Anfragen sind fast alle Anfragen, die eine Weile dauern können. Das hier als Beispiel gezeigte Beispiel ist ein einfacher Bild-Upload, aber das Skript führt einige Aufgaben im Hintergrund aus (das Bild muss in verschiedene Formate / Größen konvertiert werden und sollte auf beide Server usw. verteilt werden).
Protokolle
Ein Beispiel ist das Hochladen eines Bildes. nginx protokolliert eine '499' und eine 200 Anfrage, aber Apache empfängt (und bearbeitet!) zwei Anfragen.
Apache
[17:17:37 +0200] "POST ***URL** HTTP/1. 0" 200 9045
[17:17:47 +0200] "POST ***URL** HTTP/1. 0" 200 20687
Nginx
[17:17:47 +0200] "POST ***URL** HTTP/1.1" 499 0
[17:17:52 +0200] "POST ***URL** HTTP/1.1" 200 5641
Verdacht
Es scheint mir, dass größere / langsamere Uploads mehr darunter leiden, daher vermute ich eine Zeitüberschreitung. Ich habe versucht, den 499-Fehler nachzulesen: Schlussfolgerungen scheinen zu sein, dass es sich um eine "geschlossene Client-Verbindung" handelt. Das könnte im Hintergrund der Fall sein, aber ich bin mir nicht sicher, wie dies bedeuten würde, dass eine zweite Anfrage ausgegeben werden sollte, und es gibt sicherlich nicht so etwas wie "Benutzer geschlossener Browser".
Derzeit scheint es hilfreich zu sein, langsamere POST-Anforderungen aufzubrechen (wenn mehrere Dinge zu tun sind, lassen Sie den Benutzer einfach 1 und POST ein zweites Mal für das andere auswählen), aber dies könnte nur die Wahrscheinlichkeit verringern, dass sie auftreten. Nicht sicher.
Dies ist offensichtlich eine vorübergehende Lösung. Wenn es sich um eine Zeitüberschreitung handelt, muss ich herausfinden, wo und die entsprechenden Zahlen erhöhen, aber ich bin mir nicht sicher, warum eine Zeitüberschreitung dieses Verhalten verursachen würde: Ich würde eine Meldung "Nun, das ist schief gelaufen" vermuten, keine Wiederholung.
Fragen
Ich möchte herausfinden, durch welchen Prozess / welche Situation ein POST wiederholt werden kann. Natürlich ist auch jedes "nicht sicher warum, aber es wird durch Erhöhen dieser Zeitüberschreitung behoben" großartig.
Nginx-Konfigurationen
NGINX.conf
user nginx;
worker_processes 2;
worker_rlimit_nofile 10240;
error_log /var/log/nginx/error.log error;
pid /var/run/nginx.pid;
events {
multi_accept on;
worker_connections 4096;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nodelay off;
client_max_body_size 30m;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
conf.d
Ich habe einige IP-spezifische Zeilen in den geo
Teilen sowie die SSL
Variationen entfernt, um es einfach zu halten. Bei Bedarf kann ich sie ersetzen, aber es geo
läuft auf einen zusätzlichen Teil für die SSL-Backends und die entsprechenden Upstreams und Conf-Dateien hinaus.
geo $backend {
default apache-backend;
}
upstream apache-backend {
ip_hash;
server SERVER1 max_fails=3 fail_timeout=30s weight=2;
server SERVER2 max_fails=3 fail_timeout=30s weight=3;
}
conf.d / somestring.conf
limit_conn_zone $binary_remote_addr zone=somestring:10m;
server {
listen ip1:80;
listen ip2:80;
server_name name.tld www.name.tld;
root PATH
access_log PATH/name.log main;
location / {
proxy_pass http://$backend;
}
//*some more locations**//
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
}
conf.d / proxy.conf
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_buffering on;
proxy_read_timeout 90;
proxy_buffer_size 32k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 32k;
proxy_temp_file_write_size 32k;
nginx
kann, würde ich gerne Ihre Gedanken hören. Ich werde die Nginx-Einstellungen gleich veröffentlichen! (Ich wollte dies nicht zu einer Frage machen, bei der "Hier ist der Speicherauszug aller zufälligen Einstellungen, die ich finden konnte", und wie ich hoffentlich erklärt habe, versuche ich herauszufinden, welcher Teil der Kette verantwortlich sein kann)Antworten:
Kurze Antwort: Versuchen Sie dies für Ihren Standortblock:
Längere Erklärung:
Ich glaube, ich bin gerade auf genau das Problem gestoßen, das Sie beschrieben haben:
499
Status für diese Anforderungen an, und dieselbe Anforderung wird in verschiedenen Upstream-Knoten angezeigtEs stellt sich heraus , dass dies für nginx als Reverse - Proxy tatsächlich Standardverhalten ist, und es auf höhere Versionen eines Upgrade wird daher nicht dieses Problem beheben, obwohl es als eine mögliche Lösung gegeben wurde hier , aber diese Adressen eine andere Frage.
Dies liegt daran, dass nginx als Load Balancer einen Upstream-Knoten im Round-Robin- Verfahren auswählt . Wenn der ausgewählte Knoten ausfällt, wird die Anforderung an den nächsten Knoten gesendet. Hierbei ist zu beachten, dass Knotenfehler standardmäßig als klassifiziert werden
error or timeout
. Da Sie a nicht festgelegt habenproxy_read_timeout
, beträgt der Standardwert 60 Sekunden. Nach 60 Sekunden Wartezeit wählt nginx den nächsten Knoten aus und sendet dieselbe Anfrage.Eine Lösung besteht darin, dieses Zeitlimit zu erhöhen, damit Ihr langjähriger Vorgang abgeschlossen werden kann, z. B. durch Festlegen
proxy_read_timeout 120;
(oder eines beliebigen Grenzwerts, der Ihren Anforderungen entspricht).Eine andere Möglichkeit besteht darin, den Reverse-Proxy daran zu hindern, im Falle einer Zeitüberschreitung zu versuchen, den nächsten Knoten durch Setzen zu verwenden
proxy_next_upstream error;
. Oder Sie können beide Optionen wie oben vorgeschlagen einstellen.quelle
Aus diesem Forenthema haben wir erfahren, dass der Schuldige SPDY sein könnte. Für diesen Benutzer scheint es eine Lösung zu sein, es zu deaktivieren, und wir haben seit dem Deaktivieren auch keine doppelten Beiträge mehr.
Das genaue Problem, außer "SPDY hat es geschafft", ist derzeit nicht bekannt. Die Nebenwirkungen der vorgeschlagenen Lösung (SPDY deaktivieren) sind offensichtlich "kein SPDY mehr", aber wir können damit leben.
Bis der Fehler wieder auftaucht, nenne ich dies eine "Lösung" (oder zumindest: eine Lösung für das Problem).
edit: Wir haben dieses Problem (25-02-2014) nicht mehr gesehen, daher scheint dies in der Tat eine dauerhafte Lösung zu sein.
quelle