Kann ich feststellen, wenn ein Client die Verbindung zu einem CGI getrennt hat?

Kann ich feststellen, wenn ein Client die Verbindung zu einem CGI getrennt hat?

Ich habe ein ziemlich ressourcenintensives CGI, das ziemlich lange braucht, um mit dem Senden von Daten zu beginnen. Wir haben einige Fälle gesehen, in denen ungeduldige Leute mehrmals neu laden, was dann zusätzliche Läufe des CGI auslöst, oder Fälle, in denen der Client eine Zeitüberschreitung hat und die Verbindung abbricht, das CGI aber weiterläuft.

Gibt es eine gute Möglichkeit, festzustellen, wann dies passiert ist? Es muss nicht einmal im CGI selbst geschehen (und es ist wahrscheinlich besser, wenn es das nicht tut – es übergibt es an ein anderes Programm, über das ich keine Kontrolle habe), sondern es könnte ein Cron-Job sein, der von Zeit zu Zeit ausgeführt wird, um nach toten Verbindungen zu suchen, die er wiederherstellen kann.

Ich verwende derzeit Apache, aber das ist so problematisch, dass ich bereit wäre, einen anderen Webserver zu verwenden, wenn dieser über entsprechende Vorkehrungen verfügt (oder eine Möglichkeit bietet, das Problem zu überwachen).

Antwort1

Normalerweise können Sie eine unterbrochene Verbindung erst erkennen, wenn Sie mit dem Schreiben an den Benutzer beginnen. Andernfalls wird Ihr Prozess seine Arbeit fortsetzen, ohne den Verbindungsabbruch auf Benutzerseite zu bemerken.Dieser Beitragist verwandt, auch wenn es um PHP geht. Das Konzept sollte dasselbe sein.

Sie können Folgendes versuchen:

  1. Führen Sie die zeitaufwändige Arbeit im Hintergrund aus. Wenn ein Benutzer das CGI anfordert, führen Sie die Aufgabe nicht als normalen Blockierungsaufruf aus. Geben Sie dem Benutzer einfach etwas zurück, um ihm mitzuteilen, dass die Anforderung in Bearbeitung ist. Natürlich müssen Sie eine Möglichkeit finden, die Ansicht zu aktualisieren oder eine andere Seite bereitzustellen, auf der der Auftragsstatus mithilfe einer Anforderungs-ID oder IP überprüft werden kann.
  2. Senden Sie die Daten so schnell wie möglich an den Client zurück und beenden Sie den Vorgang, wenn das Senden fehlgeschlagen ist (Hinweis auf unterbrochene Verbindung). Sie können beispielsweise alle paar Sekunden oder Minuten den Fortschritt des Auftrags senden.

Wenn Sie die aktuell laufenden Jobs in einer Datenbank speichern, können Sie die Anforderungs-ID und/oder die Client-IP-Adresse speichern. So können Sie doppelte Anforderungen an dieselbe Ressource erkennen und ignorieren und dem Benutzer mitteilen, dass „Ihre Anforderung in Bearbeitung ist“.

Antwort2

Achtung: Diese Informationen können veraltet sein. Siehe letzter Absatz.

Ich erinnere mich, das gleiche Problem gehabt zu haben und es mit einemnph(kein Parseheader) CGI-Skript.

Normalerweise sammelt Apache alle Header aus Ihrem Skript und ergänzt sie nach dem Lesen der Header mit einigen Standardheadern, die Sie nicht angegeben haben. Das bedeutet auch, dass Apache überhaupt nichts an den Client sendet, solange Sie die Header nicht fertigstellen.

Bei einem NPH-Skript müssen Sie alle Header angeben, aber Apache sendet sie sofort an den Client und sendet Ihrem CGI-Skript ein SIGPIPE, sobald der Client die Verbindung trennt. Sie können also X-Slowly-Counting-Part-nnn: yesalle paar Sekunden einen Header senden, um Timeouts auf dem Client zu verhindern, und Sie werden benachrichtigt, wenn der Client die Verbindung trennt.

Das Problem besteht immer noch darin, dass Sie zuerst den HTTP-Status senden müssen. Wenn Sie jedoch eine 'Content-Length: 0' oder vielleicht eine 'Content-Length: 1' senden und die Verbindung schließen, ohne Inhalte zu senden, wird Ihr Datei-DownloadersollenGehen Sie von einem Netzwerkfehler aus und handeln Sie entsprechend.

Sie müssen die Ausgabe des anderen Programms wahrscheinlich durch Ihren Prozess leiten, aber das sollte zumindest unter Linux und bei Verwendung des sendfile(2)Systemaufrufs keine nennenswerten Leistungseinbußen bedeuten.

Das Problem dabei ist, dass ich es vor mindestens 10 Jahren verwendet habe, wahrscheinlich auf Apache 1.3, und das Googeln danach apache cgi nphhat nichts Nützliches ergeben. Vielleicht wurde die NPH-Funktion in der Zwischenzeit entfernt – vielleicht aber auch nicht, ich gebe zu, ich habe nicht sehr gründlich gesucht.

Antwort3

Alte Frage, aber ich hatte dasselbe Problem und habe es gelöst, indem ich überprüft habe, ob die Verbindung hergestellt ist:

In meinem Fall führe ich ein Bash-Skript auf dem Server aus. Die Umgebungsvariablen werden von mod_cgi exportiert. Ich glaube, diese Lösung funktioniert für jedes Programm/Skript, das auf CGI ausgeführt wird.

ss -nt state established "( sport = :$SERVER_PORT and dport = $REMOTE_ADDR:$REMOTE_PORT )" 2>/dev/null | grep -q "$REMOTE_ADDR:$REMOTE_PORT"
if [ "$?" -ne '0' ]; then
     # Client closed browser/connection
fi

verwandte Informationen