Fragen zum requests Modul

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Hallo :)

Im Zusammenhang zu diesem Thema:
viewtopic.php?p=313777#p313777
möchte ich mich hier ein wenig mehr zum requests modul informieren.

In dem obigen Thema geht es darum, dass ich rausfinden möchte, wieso ich relativ häufig (1%, dennoch zu häufig) keine Antwort von der website bekomme, zu der ich einen requests API Call mache.
Der Betreiber der Website hat mir freundlicherweise Auszüge aus ihren Logs geschickt, woraus ersichtlich wird, dass beinahe alle meine unerfolgreichen API Calls, niemals bei ihnen angekommen sind.
Wenn ich direkt danach den Call wiederhole, funktioniert er eigentlich fast immer.
Nur kann ich das aleider nicht zur Standardvorgehensweise machen, da ich immer wissen muss, ob der Call angekommen ist, oder nicht. Es wäre fatal, wenn ein Call unbemerkt doppelt bei der website ankommt.

Da ich leider mit dem obigen Thema nicht weiterkomme (Überwachung des Netzwerks um die ursache zu finden), dachte ich es wäre zumindest ein Anfang, wenn ich bei mir im PYthon Skript irgendwie testen könnte, ob der API Call überhaupt korrekt losgeschickt wurde. Vllt lässt sich mit requests ja feststellen, dass der Call nicht losgeschickt wurde und ich wiederhole ihn dann einfach nochmal.

Situation:
Ich verwende
http://docs.python-requests.org/en/mast ... /advanced/
Im __init__ wird eine self.session = requests.session() gestartet und für den API Call dann entsprechend:

Code: Alles auswählen

response = self.session.request(http_method,self.url + self.apiversion + '/' + urladdon, data=params,headers=headers,timeout=tout)
return (response.json() )
gemacht.

Gibt es mit requests oderso eine Möglichkeit rauszufinden, ob der Call erfolgreich verschickt wurde? Könnte ja zb sein, dass aus irgendeinem Grund die Session kurzzeitig geschlossen wurde (zb vom Server Anbieter auf dem das Skript läuft)?
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich behaupte mal: das geht nicht. Es ist in dem Szenario durchaus denkbar, dass

- dein Request durchkommt.
- der Server das Request bearbeitet.
- eine Antwort vorbereitet und abschickt.
- in diesem Moment etwas schief geht auf dem Weg der Pakete vom Server zurueck zu dir.

Solange du ueber den Zustand der Requests auf seiten des Servers nichts erfahren kannst (also danach eine weitere Abfrage machst, welche den Effekt der ersten prueft), ist das leider nicht detektierbar, ob das Request nun durchkam, oder der Fehler schon vorher stattfand. Der Fehler ist in beiden Faellen eine broken pipe, und mehr kann man da nicht machen.
BlackJack

@Serpens66: So ganz allgemein um zu wissen ob eine Anfrage beim Server angekommen ist, musst Du die Antwort auswerten. Ohne Antwort, kannst Du auch nicht sicher sein ob und was der Server von einer Anfrage mitbekommen hat.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Serpens66 hat geschrieben: Der Betreiber der Website hat mir freundlicherweise Auszüge aus ihren Logs geschickt, woraus ersichtlich wird, dass beinahe alle meine unerfolgreichen API Calls, niemals bei ihnen angekommen sind.
Wenn ich direkt danach den Call wiederhole, funktioniert er eigentlich fast immer.
?
Grundsätzlich können zwischen dem Client und dem Webserver noch verschiedene Dinge (auf HTTP-Ebene z.B. irgendein Proxy, der falsch konfiguriert ist) liegen, die (mit unterschiedlicher Wahrscheinlichkeit) dafür sorgen, dass die Anfragen nicht in den Webserver-Logs des API-Anbieters auftauchen, also dort nicht ankommen. Insbesondere würde ich noch einmal schauen, ob die fehlschlagenden Requests überhaupt den Client verlassen. Dazu könntest du z.B. versuchen, die Kommunikation mit der API mit einem Webserver, auf den du vollen Zugriff hast (lokal zum Beispiel) zu simulieren und so Fehler in deiner Applikation ausschließen.

BlackJack hat ja schon angedeutet, dass du -- wenn alles klappt -- eigentlich einen entsprechenden Status-Code (20* ) bekommen müsstest. Wenn du den nicht auswertest, wie hast du dann die 1% errechnet? Wenn du die Requests, die fehlschlagen identifizieren kannst, wäre ja interessant, ob die bestimmte Charakteristika aufweisen.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

nezzcarth hat geschrieben:Insbesondere würde ich noch einmal schauen, ob die fehlschlagenden Requests überhaupt den Client verlassen. Dazu könntest du z.B. versuchen, die Kommunikation mit der API mit einem Webserver, auf den du vollen Zugriff hast (lokal zum Beispiel) zu simulieren und so Fehler in deiner Applikation ausschließen.
Genau, ob meine requests überhaupt losgeschickt werden, ist ja genau die Fragestellung dieses Threads (der andere Thread ist für die fragestellung, "falls es von mir alles korrekt losgeschickt wird, wie analysiere ich es dann")
Ich versteh deinen Lösungsvorschlag leider nicht. Mein Skript läuft auf einem Webserver bei einem server-anbieter.
nezzcarth hat geschrieben: BlackJack hat ja schon angedeutet, dass du -- wenn alles klappt -- eigentlich einen entsprechenden Status-Code (20* ) bekommen müsstest. Wenn du den nicht auswertest, wie hast du dann die 1% errechnet? Wenn du die Requests, die fehlschlagen identifizieren kannst, wäre ja interessant, ob die bestimmte Charakteristika aufweisen.
Ist es nicht das Charakteritika eines "timeouts" dass es eben keine Antwort gibt? Deswegen verwundern mich eure Antworten ein wenig.
Die Logs des Betreibers der Website bestätigen es ja nochmal, dass meine Calls garnicht bei ihnen ankommen. Also wie kann es dann jemals eine Antwort geben, die ich in irgendeinerweise auswerten könnte? Oder antwortet mir irgendwann wer anders??

Auf die ~1% komm ich, weil wenn nach 30 sekunden keine Antwort kommt, requests einen timeout error raised. Und die Fälle habe ich mit den logs des Betreibers abgeglichen und festgestellt, dass all diese Calls niemals bei denen ankamen. Ich hätte also auch hundert Jahre warten können, ohne dass eine Antwort gekommen wäre. Oder etwa nicht?

Leider ist kein Muster erkennbar, es scheint willkürlich calls zu treffen.
BlackJack

@Serpens66: Timeout sagt nichts darüber aus ob die Anfrage angekommen ist und verarbeitet wurde oder nicht. Das sagt nur das die Antwort bis dahin noch nicht gekommen ist, egal warum, und das Du/Dein Client aufgibt darauf zu warten. Die Anfrage kann noch auf dem Weg sein, oder sogar schon angekommen und verarbeitet worden sein. Das kann man schlicht nicht sagen. Wie denn auch? Dafür müsste man eine definitive Antwort vom Server bekommen, denn nur der weiss das letztendlich.

Es kann sein dass Du 100 Jahre warten kannst und *keine* Antwort bekommst, es kann aber auch sein das die Anfrage nach 10 Minuten doch durch kommt. Oder nach 20, oder…

Okay 100 Jahre wahrscheinlich nicht, aber die Timeout-Zeiten bei TCP sind generell recht grosszügig, also bei den Servern auf dem Weg bis zum Ziel. Allerdings wird dann irgendwann die Verbindung abgebrochen, wodurch Du immer noch nicht weisst ob Deine Anfrage durchgekommen ist und eventuell auch verarbeitet wurde, oder ob es die Antwort nicht zurück geschafft hat. *Das* kannst Du an Deinem Ende nur heraus finden wenn die API ermöglicht den Effekt hinterher mit weiteren Anfragen festzustellen. Was __deets__ ja bereits sagte.

Um das noch mal klar zu sagen: Wenn die API *das* nicht ermöglicht, dann kannst Du nicht in jedem Fall 100%ig sicherstellen das ein API-Aufruf garantiert genau *einmal* erfolgt.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

BlackJack hat geschrieben:@Serpens66: Timeout sagt nichts darüber aus ob die Anfrage angekommen ist und verarbeitet wurde oder nicht. Das sagt nur das die Antwort bis dahin noch nicht gekommen ist, egal warum, und das Du/Dein Client aufgibt darauf zu warten. Die Anfrage kann noch auf dem Weg sein, oder sogar schon angekommen und verarbeitet worden sein. Das kann man schlicht nicht sagen. Wie denn auch? Dafür müsste man eine definitive Antwort vom Server bekommen, denn nur der weiss das letztendlich.

Es kann sein dass Du 100 Jahre warten kannst und *keine* Antwort bekommst, es kann aber auch sein das die Anfrage nach 10 Minuten doch durch kommt. Oder nach 20, oder…

Okay 100 Jahre wahrscheinlich nicht, aber die Timeout-Zeiten bei TCP sind generell recht grosszügig, also bei den Servern auf dem Weg bis zum Ziel. Allerdings wird dann irgendwann die Verbindung abgebrochen, wodurch Du immer noch nicht weisst ob Deine Anfrage durchgekommen ist und eventuell auch verarbeitet wurde, oder ob es die Antwort nicht zurück geschafft hat. *Das* kannst Du an Deinem Ende nur heraus finden wenn die API ermöglicht den Effekt hinterher mit weiteren Anfragen festzustellen. Was __deets__ ja bereits sagte.

Um das noch mal klar zu sagen: Wenn die API *das* nicht ermöglicht, dann kannst Du nicht in jedem Fall 100%ig sicherstellen das ein API-Aufruf garantiert genau *einmal* erfolgt.
Prinzipiell trifft das auf timeouts ja zu, stimmt.
Aber hier im speziellen hab ich ja extra dazu erwähnt, dass die Betreiber diese speziellen Calls niemals erhalten haben (auch Tage später nicht). Daher ist es hier doch 100% sicher, dass warten nichts bringt, oder wo irre ich mich?

Mit einem weiteren API Call feststellen ob der vorherige durchgekommen ist, ist leider aktuell nicht möglich (schon garnicht falls der Call nach x Minuten dann plötzlich doch noch eingeht). Ich habe dazu aber schon einen Vorschlag eingereicht, wie das in Zukunft möglich sein kann und der Betreiber hat mir zugestimmt.

Aber du bringst mich auf eine Idee... der Hauptgrund weshalb ich eine timeout Zeit festlege ist ja, dass mein ganzes Programm geblockt wird, bis ich endlich eine Antwort bekomme. Ich könnte ja aber auch das Programm nach Ablauf der Zeit weiterlaufen lassen, während ein Thread weiterhin auf eine mögliche Antwort wartet. Auf die Weise würde ich zumindest "spätzünder" die x Minuten brauchen, dennoch erkennen und wüsste ob und wann sie durchgekommen sind. Nur für wie lang setze ich da das wartelimit? 60 Minuten? 24 Stunden ? Tage?


Aber um nochmal auf das eigentliche Thema dieses Threads zurückzukommen:
Hier möchte ich ja rausfinden, ob es vllt doch an meiner Verbindung liegt. Ich hatte gegenüber dem Betreiber der website argumentiert, dass ich requests.session verwende und dies eigentlich dauerhaft für eine intakte Verbnindung sorgt, sodass die Verbindung nicht abbrechen könne.
Dieser erwiderte darauf allerdings, dass manche server-Anbieter solche Verbindungen auch ab und zu beenden könnten und dass das die Ursache dafür sein könnte, dass bei ihnen nichts ankommt (auch nicht verzögert).
Deswegen hatte ich hier gefragt, ob ich mit requests irgendwie überprüfen kann, obs erfoglreich losgeschickt wurde... aber vermutlich sorgt das requests modul schon selbst dafür, dass es losgeschickt wird bzw würde einen Fehler raisen, wenn es nicht klappt?
BlackJack

@Serpens66: Wenn Du nach 30 Sekunden wegen Timeout abbrichst, dann wird die Verbindung abgebrochen. Das wird auch weiter kommuniziert. Das heisst auch wenn der Server-Betreiber sagt es ist nichts angekommen, das nicht zwangsläufig bedeutet es wäre auch dann nichts angekommen wenn Du nicht abgebrochen hättest. Insofern kann man nicht 100% sicher sein das warten nichts bringt.

Im letzten Satz verstehe ich nicht so ganz was Du da testen möchtest und was Dir das bringen sollte. Du musst den Datenverkehr auf einer niedrigeren Ebene untersuchen als das was dir `requests` bietet, um zu sehen wo und warum es hängt, und kannst das auch nur dort tun wo Du Zugriff drauf hast. Ausnahmen bekommst Du denke ich mal nur wenn die TCP-Schicht meldet das die Verbindung abgebrochen wurde oder wenn es eine Zeitüberschreitung gab. Die Gründe dafür musst Du anders heraus finden. Wirklich viel mehr gibt ja schon die Socket-API nicht wirklich her.
Antworten