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.
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
@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