Wie kann ich Tornado und Redis asynchron?
Ich versuche zu finden, wie kann ich Redis und Tornado asynchron. Ich fand die tornado-redis, aber ich brauche mehr als nur ein yield
im code.
Ich habe den folgenden code:
import redis
import tornado.web
class WaiterHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
client = redis.StrictRedis(port=6279)
pubsub = client.pubsub()
pubsub.subscribe('test_channel')
for item in pubsub.listen():
if item['type'] == 'message':
print item['channel']
print item['data']
self.write(item['data'])
self.finish()
class GetHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello world")
application = tornado.web.Application([
(r"/", GetHandler),
(r"/wait", WaiterHandler),
])
if __name__ == '__main__':
application.listen(8888)
print 'running'
tornado.ioloop.IOLoop.instance().start()
Muss ich immer Zugriff auf die /
url und Holen Sie sich die "Hallo Welt", solange es eine Anforderung noch in der /wait
.
Wie kann ich es tun?
- Redis pub/sub sollte nicht verwendet werden
web.RequestHandler
, weil es blockiert die ioloop während der Wartezeit aufpubsub.listen()
. Haben Sie einen Blick auf tornadogists.org/532067 für eine funktionierende websocket-Beispiel. - Das websocket ist eine gute option, aber meine Anwendung benötigt werden, arbeiten in Browsern, die nicht über Unterstützung für websockets. Ich bin mit long polling. Das ist der Grund, ich brauche ein 'async Holen.
- in diesem Fall Ihre beste Wette ist die Aufrechterhaltung eines lokalen Zustand des abonnierten Kanal Geschichte (zugeführt durch einen separaten thread), und dann schreiben, dass der Staat sofort auf die Antwort und füllen Sie die
get
Betrieb. Der client sollte halten einige Rekorde der letzten index -, oder in letzter Zeit bekommen, etc., so dass Sie, um die Kontinuität für verschiedene Kunden. Ich werde schreiben, bis eine Antwort mit einem Beispiel, in ein paar Stunden wenn ich Zeit dazu.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollten Sie nicht verwenden Redis pub/sub in der Haupt-Tornado-thread auf, da er verhindert, dass der IO-Schleife. Können Sie umgehen das lange Abfragen von web-clients in der Haupt-thread, aber man sollte erstellen Sie einen separaten thread für das hören von Redis. Sie können dann mit
ioloop.add_callback()
und/oder einethreading.Queue
für die Kommunikation mit dem Haupt-thread, wenn Sie Nachrichten erhalten.Müssen Sie die Verwendung von Tornado IOLoop kompatibel redis-client.
Gibt es nur wenige von Ihnen zur Verfügung, toredis, brukva, etc.
Hier ist pubsub Beispiel in toredis: https://github.com/mrjoes/toredis/blob/master/tests/test_handler.py
Python >= 3.3, würde ich Ihnen raten, zu verwenden,aioredis.
Ich habe nicht testen Sie den code unten, aber es sollte etwas sein wie:
Okay, also hier mein Beispiel, wie ich es tun würde, mit Anfragen bekommen.
Fügte ich zwei Hauptkomponenten:
Die erste ist eine einfache Gewinde-pubsub-listener, der fügt neue Nachrichten in eine lokale Liste-Objekt.
Ich habe auch Liste Accessoren der Klasse, damit Sie Lesen können, die von der listener-thread, als ob Sie Lesen würden, aus einer normalen Liste. So weit wie Ihre
WebRequest
betroffen ist, die Sie gerade Lesen von Daten aus einer lokalen Liste-Objekt. Dies gibt sofort einen Wert zurück und nicht blockieren aktuelle Anforderung abgeschlossen oder zukünftige Anfragen akzeptiert und verarbeitet.Die zweite ist die ApplicationMixin Klasse. Das sekundäre Objekt, dass Sie Ihre web-Anfrage-Klasse Erben, um zum hinzufügen von Funktionen und Parametern. In diesem Fall überprüft es, ob ein Kanal listener bereits vorhanden ist für den angeforderten Kanal, erstellt, falls keines gefunden wurde, und gibt dem Hörer Griff, um dem WebRequest.
Den WebRequest-Klasse behandelt nun die Zuhörer, als ob es eine statische Liste (eingedenk der Tatsache, dass Sie brauchen, um zu geben
self.write
string)Schließlich, nachdem die Anwendung erstellt ist, ich Hinzugefügt ein leeres-Wörterbuch als ein Attribut
Sowie einige Bereinigung der Laufenden threads, sobald Sie die Anwendung beenden
Der vollständige code:
Empty
Ausnahmen ordnungsgemäß.