Python Tornado - machen POST Rückkehr sofort während asynchroner Funktion Arbeits hält

StackOverflow https://stackoverflow.com/questions/3869421

  •  28-09-2019
  •  | 
  •  

Frage

so habe ich einen Handler unter:

class PublishHandler(BaseHandler):

    def post(self):
        message = self.get_argument("message")
        some_function(message)
        self.write("success")

Das Problem, das ich bin vor, dass some_function () einige Zeit in Anspruch nimmt ausführen und ich würde die Post-Anforderung gerne sofort zurück, wenn sie aufgerufen und für some_function (), wenn möglich, in einem anderen Thread / Prozess ausgeführt werden.

Ich bin mit Berkeley DB als Datenbank und was ich versuche zu tun ist relativ einfach.

habe ich eine Datenbank von Benutzern jeweils mit einem Filter. Wenn die Filter die Nachricht übereinstimmt, wird der Server die Nachricht an den Benutzer senden. Derzeit teste ich mit Tausenden von Benutzern und daher bei jeder Veröffentlichung einer Mitteilung über eine Post-Anforderung an es Iterieren durch Tausende von Benutzern Übereinstimmung. Das ist meine naive Implementierung, Dinge zu tun und daher meine Frage. Wie mache ich das besser?

War es hilfreich?

Lösung

Das könnte Sie der Lage sein, dies zu tun, indem Sie Ihre IOLoop des add_callback Methode wie folgt:

loop.add_callback(lambda: some_function(message))

Tornado wird den Rückruf in dem nächsten IOLoop Pass ausführen, die kann (Ich habe in Tornado Eingeweide graben, um sicher zu wissen, oder alternativ testen) erlaubt der Anforderung abzuschließen, bevor das Code wird ausgeführt.

Der Nachteil ist, dass lang andauernde Code, den Sie geschrieben haben, wird noch Zeit in Anspruch nehmen auszuführen, und dies kann eine weitere Anforderung am Ende blockiert. Das ist nicht ideal, wenn Sie viele dieser Wünsche haben kommen auf einmal.

Je mehr narrensichere Lösung ist es in einem eigenen Thread oder Prozess auszuführen. Die am besten Weg mit Python ist ein Verfahren zu verwenden, aufgrund der GIL (ich sehr auf das Lesen von oben würde empfehlen, wenn Sie nicht mit ihm vertraut sind). Allerdings auf einer Single-Prozessor-Maschine die Gewinde Implementierung wird genauso gut funktionieren, und kann einfacher zu implementieren sein.

Wenn Sie die Gewinde Route gehen, kann man einen schönen „async Testamentsvollstrecker“ Modul mit einem Mutex, einem Faden und einer Warteschlange bauen. Schauen Sie sich die multiprocessing Modul, wenn Sie die Route der Verwendung eines separaten Prozess gehen.

Andere Tipps

Ich habe das versucht, und ich glaube, dass die Anforderung nicht abgeschlossen wird, bevor die Rückrufe aufgerufen werden.

ich denke, ein schmutziger Hack wäre zwei Ebenen von add_callback zu nennen, z.

  def get(self):
    ...
    def _defered():
      ioloop.add_callback(<whatever you want>)
    ioloop.add_callback(_defered)
    ...

Aber das sind Hacks am besten. Ich bin auf der Suche nach einer besseren Lösung gerade jetzt, werde wahrscheinlich mit einiger Message Queue oder einfacher Thread Lösung enden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top