Twisted Deferred vs Blocking in Web-Services

8

Ich habe Schwierigkeiten, das gleiche Verhalten in Web-Service-Code zu erzeugen, der verzögerte Objekte wie in Code verwendet, der dies nicht tut. Mein Ziel ist es, einen Decorator zu schreiben, der die Verarbeitung jeder Methode (die von Twisted abgekoppelt ist) an den Twisted-Thread-Pool delegiert, sodass der Reaktor nicht blockiert wird, ohne die Semantik der Methode zu ändern.

Wenn eine Instanz des Klassenechos unten als Webdienst verfügbar gemacht wird, lautet dieser Code:

%Vor%

zeigt dem Browser ein HTML-Dokument an, wenn alle raise-Anweisungen auskommentiert sind, und zeigt einen schön formatierten Stack-Trace (was Twisted für mich tut), wenn die raise-Anweisung "E5" eingeschlossen ist. Das ist was ich will. Wenn ich überhaupt keine verzögerten Objekte verwende und das gesamte Verhalten von callback1 und callback2 innerhalb von render_GET () aufbringe, erzeugt eine Ausnahme innerhalb von render_GET die gewünschte Stapelverfolgung.

Ich versuche Code zu schreiben, der sofort auf den Browser reagiert, keine Ressourcenverluste in Twisted verursacht und dazu führt, dass der Browser-Stack-Trace auch in den Fällen angezeigt wird, in denen eine der raise-Anweisungen "E1" bis "E3" ist im verzögerten Code enthalten - obwohl ich natürlich verstehe, dass die Stack-Spuren selbst anders sein werden. (Der "E4" -Fall interessiert mich nicht so sehr.) Nachdem ich die Twisted-Dokumentation und andere Fragen auf dieser Seite gelesen habe, bin ich mir nicht sicher, wie ich das erreichen kann. Ich hätte gedacht, dass das Hinzufügen eines Fehlerbacks dies erleichtern könnte, aber offensichtlich nicht. Es muss etwas an den verzögerten Objekten und dem twisted.web-Stapel sein, die ich nicht verstehe.

Die Auswirkungen auf die Protokollierung, die ich hier dokumentiere, können durch die Verwendung von PythonLoggingObserver beeinflusst werden, um die Twisted-Protokollierung mit dem Standardprotokollierungsmodul zu verbinden.

Wenn "E1" eingeschlossen ist, wartet der Browser, bis der Reaktor heruntergefahren wird. An diesem Punkt wird die ValueError-Ausnahme mit Stack-Trace protokolliert und der Browser erhält ein leeres Dokument.

Wenn "E2" eingeschlossen ist, wird die ValueError-Ausnahme mit Stack-Trace sofort protokolliert, aber der Browser wartet, bis der Reaktor heruntergefahren wird, an diesem Punkt erhält er ein leeres Dokument.

Wenn "E3" eingeschlossen ist, wird die ValueError-Ausnahme mit Stack-Trace sofort protokolliert, der Browser wartet, bis der Reaktor heruntergefahren wird, und empfängt an diesem Punkt das gewünschte Dokument.

Wenn die raise-Anweisung "E4" enthalten ist, wird das beabsichtigte Dokument sofort an den Browser zurückgegeben, und die ValueError-Ausnahme mit Stack-Trace wird sofort protokolliert. (Gibt es in diesem Fall eine Möglichkeit eines Ressourcenlecks?)

    
wberry 05.05.2011, 22:14
quelle

2 Antworten

4

Ok, nachdem ich deine Frage mehrere Male gelesen habe, glaube ich zu verstehen, was du fragst. Ich habe auch Code überarbeitet, um ein wenig besser als Ihre ursprüngliche Antwort zu machen. Diese neue Antwort sollte alle Befugnisse von Deferred's zeigen.

%Vor%

Ich empfehle auch, dass Sie das krondo Tutorial lesen. Es wird Ihnen alles beibringen, was Sie über Deferred wissen müssen.

Bearbeiten:

Habe den obigen Code modifiziert, um einige dumme Bugs zu beheben. Verbesserte es auch. Wenn eine Ausnahme irgendwo auftritt (außer in self.errback , aber wir brauchen eine gewisse Vertrauensstufe), wird sie an self.errback übergeben, die den Fehler in twisted protokolliert oder druckt und dann den Trace an den Browser und sendet Schließen Sie die Anfrage. Dies sollte Ressourcenlecks stoppen.

    
thomas 06.05.2011, 14:44
quelle
1

Ich habe es herausgefunden, indem ich durch die Twisted-Quelle gegraben habe. Die notwendige Einsicht besteht darin, dass die Logik für die Reaktion des Reaktors und die Verzögerte Rückruf- / Fehlerkettenlogik von dem Anforderungsobjekt entkoppelt ist, wodurch die Daten zurück zum Browser gelangen. Der Fehlerrücklauf ist notwendig, kann aber nicht einfach das Fehlerobjekt in der Kette weiterleiten, wie im ursprünglichen Code, den ich gepostet habe. Der Fehler muss den Fehler dem Browser melden.

Der unten stehende Code entspricht meinen Anforderungen (hält den Browser nie im Wartestatus, liefert immer den Stack-Trace, erfordert keinen Neustart des Reaktors, um die Dinge wieder in Gang zu bringen) und erlaubt mir, Blockierungsmethoden zu dekorieren und sie an Threads zu delegieren der Reaktor spricht auf andere Ereignisse an (solche Methoden werden hier im wesentlichen die Stelle von callback1 einnehmen). Ich habe jedoch festgestellt, dass das Auskommentieren der E4-Anweisung "raise" im folgenden Code ein sehr merkwürdiges Verhalten bei nachfolgenden Browseranforderungen erzeugt (teilweise Daten von früheren Anfragen, die an den Browser zurückgegeben wurden; Deadlock).

Hoffentlich finden andere, dass dies ein nützliches Beispiel ist.

%Vor%     
wberry 06.05.2011 14:21
quelle