2017-05-25 3 views
2

Ich sehe eine seltsame Situation, in der entweder Nginx oder uwsgi eine lange Warteschlange mit eingehenden Anfragen aufzubauen versucht und versucht, sie zu verarbeiten, lange nachdem die Clientverbindung abgelaufen ist. Ich würde es gerne verstehen und dieses Verhalten stoppen. Hier weitere Informationen:Nginx gibt uWSGI sehr alte Anfragen?

Mein Setup

Mein Server Nginx verwendet passieren HTTPS POST-Anfragen an uwsgi und Kolben über eine Unix-Datei Buchse. Ich habe grundsätzlich die Standardkonfigurationen für alles.

Ich habe einen Python-Client, der 3 Anfragen pro Sekunde an diesen Server sendet.

Das Problem

den Client für ca. 4 Stunden Nach dem Ausführen begann die Client-Maschine, dass die Verbindungen heraus wurden Timing alle berichten. (Es verwendet die Python-Anforderungsbibliothek mit einem Timeout von 7 Sekunden.) Etwa 10 Minuten später änderte sich das Verhalten: Die Verbindungen begannen mit 502 Bad Gateway zu versagen.

Ich schaltete den Client aus. Aber etwa 10 Minuten NACH dem Ausschalten des Clients zeigten die serverseitigen uWSGI-Protokolle, dass uWSGI versuchte, Anfragen von diesem Client zu beantworten! Und top zeigte uWSGI mit 100% CPU (25% pro Arbeiter).

Während dieser 10 Minuten jeder uwsgi.log Eintrag sah wie folgt aus:

Thu May 25 07:36:37 2017 - SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request /api/polldata (ip 98.210.18.212) !!! Thu May 25 07:36:37 2017 - uwsgi_response_writev_headers_and_body_do(): Broken pipe [core/writer.c line 296] during POST /api/polldata (98.210.18.212) IOError: write error [pid: 34|app: 0|req: 645/12472] 98.210.18.212() {42 vars in 588 bytes} [Thu May 25 07:36:08 2017] POST /api/polldata => generated 0 bytes in 28345 msecs (HTTP/1.1 200) 2 headers in 0 bytes (0 switches on core 0)

Und die Nginx error.log eine Menge von dieser zeigt:

2017/05/25 08:10:29 [error] 36#36: *35037 connect() to unix:/srv/my_server/myproject.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 98.210.18.212, server: example.com, request: "POST /api/polldata HTTP/1.1", upstream: "uwsgi://unix:/srv/my_server/myproject.sock:", host: "example.com:5000"

Nach etwa 10 Minuten wurde die uwsgi Aktivität stoppt. Wenn ich den Client wieder einschalte, akzeptiert Nginx glücklich die POST-Anfragen, aber uWSGI gibt bei jeder Anfrage den gleichen "Schreiben an eine geschlossene Pipe" -Fehler aus, als ob es irgendwie dauerhaft defekt wäre. Durch das Neustarten des Andock-Containers des Webservers wird das Problem nicht behoben, aber durch einen Neustart des Host-Computers wird das Problem behoben.

Theories

In der Standard-Nginx -> socket -> uwsgi Konfiguration gibt es eine lange Schlange von Anforderungen ohne Timeout? Ich schaute in die uWSGI Dokumentation und ich sah eine Reihe von konfigurierbaren Timeouts, aber alle standardmäßig auf etwa 60 Sekunden, so dass ich nicht verstehen kann, wie ich 10 Minuten alte Anfragen verarbeitet bekomme. Ich habe keine Standard-Timeout-Einstellungen geändert.

Die Anwendung verwendet fast alle 1 GB RAM in meinem kleinen dev-Server, so denke ich, Ressourcengrenzen können das Verhalten auslösen.

Wie auch immer, ich möchte meine Konfiguration ändern, so dass Anfragen> 30 Sekunden alt mit einem 500 Fehler fallengelassen werden, anstatt von uWSGI verarbeitet zu werden. Ich würde mich über jeden Rat, wie man das macht, und über Theorien darüber, was passiert, freuen.

Antwort

1

Dies scheint ein Problem auf der uWSGI-Seite zu sein.

Es klingt wie Ihr Back-End-Code möglicherweise fehlerhaft ist, dass es takes too long verarbeitet, um die Anforderungen zu verarbeiten, implementiert keine Art von Begrenzung für die Anforderungen und nicht ordnungsgemäß abfangen, wenn eine der zugrunde liegenden Verbindungen beendet wurden (daher , erhalten Sie die Fehler, die Ihr Code versucht, in geschlossene Pipelines zu schreiben und möglicherweise sogar neue Anfragen zu verarbeiten, lange nachdem die zugrunde liegenden Verbindungen beendet wurden.

+1

Danke; Diese Erklärungen machen Sinn - im Grunde füllt nginx uwsgis Socket mit Anfragen und ignoriert die Tatsache, dass uwsgi sie nicht verarbeitet. Seltsam, dass die Standardkonfiguration dies erlaubt; Ich hätte gedacht, dass uwsgi zumindest ein Timeout haben würde, basierend darauf, wie lange die eingehende Anfrage im Socket sitzt. Die Einstellung 'ignore_client_abort' ist interessant; Ich werde es versuchen. (Die Harakiri-Einstellung hat es nicht gelöst.) – Luke

+0

@Luke, yeah, ich denke, im Grunde genommen macht uWSGI eine konservative Annahme, dass Sie vielleicht keine Anfragen fallen lassen wollen, selbst wenn Clients sofort trennen; Es scheint zumindest, dass Sie Ihr Backend zumindest dahingehend anpassen möchten, dass der Client zumindest dann noch verbunden ist, wenn Sie mit der Verarbeitung der Anfrage beginnen. Außerdem eine interessante Lektüre darüber, die verspäteten Anfragen vollständig fallen zu lassen - http://ferd.ca/rtb-where-erlang-blooms.html – cnst

0

Scheint wie DoS-Angriff auf Nginx uWSGI, die 100% CPU-Auslastung mit Nginx 502, 504, 500 zurückgibt. IP-Spoofing ist in DoS-Angriff üblich. Ausschließen durch Überprüfen der Protokolle.

Verwandte Themen