私はAJAX経由で "コマンド"を収集し、長いポーリングでクライアントにコマンドを配布するWebサーバーを構築しようとしています。Python Tornado - 長いポーリングサーバーを実装してキューから読み取る方法
目標は、誰かが/ addコマンドにデータをPOSTすることです。
もう1つのクライアントは、コマンドの実行を待機しているロングポーリングクライアントを実装しています。
キューは、注意を待っているコマンドを保持するために使用する正しいデータ構造です。私はコマンドを基本的にすぐに任意の長いポーリングクライアントに配布するが、クライアントが現在ポーリングしていない場合は保持することを望む。
ここは私のpythonスクリプトです。
import os
import time
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.gen
import Queue
import multiprocessing.pool
import mysql.connector
import urlparse
import uuid
import json
_commandQueue = Queue.Queue()
_commandPollInterval = 0.2
_commandPollTimeout = 10
class HomeHandler(tornado.web.RequestHandler):
def get(self):
self.render("home.htm")
class AddCommandHandler(tornado.web.RequestHandler):
def post(self):
d = urlparse.parse_qs(self.request.body)
_commandQueue.put(d)
self.write(str(True))
class PollHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
self.write("start")
d = 1
d = yield self.getCommand()
self.write(str(d))
self.write("end")
self.finish()
@tornado.gen.coroutine
def getCommand(self):
start = time.time()
while (time.time() - start) < _commandPollTimeout * 1000:
if not _commandQueue.empty:
return _commandQueue.get()
else:
time.sleep(_commandPollInterval)
return None
def main():
application = tornado.web.Application(
[
(r"/", HomeHandler),
(r"/add-command", AddCommandHandler),
(r"/poll", PollHandler),
],
debug=True,
template_path=os.path.join(os.path.dirname(__file__), "templates"),
static_path=os.path.join(os.path.dirname(__file__), "static"),
)
tornado.httpserver.HTTPServer(application).listen(int(os.environ.get("PORT", 5000)))
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
AddCommandHandler
は_commandQueue
にアイテムを入れて正常に動作します。
PollHandler
リクエストがタイムアウトしました。私がPollHandler
と呼ぶと、_commandQueue
がロックされているように見えます。
私はキューに参加する必要があると思うが、私はコードでそれを行うための適切な時間を見つけることができないようだ。
UPDATE - ここでは、ブロックは、入力ストリームからの読み込みいるので、私の最終的なコードの答えのおかげで
import os
import time
import datetime
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.gen
import tornado.queues
import urlparse
import json
_commandQueue = tornado.queues.Queue()
_commandPollInterval = 0.2
_commandPollTimeout = 10
class HomeHandler(tornado.web.RequestHandler):
def get(self):
self.render("home.htm")
class AddCommandHandler(tornado.web.RequestHandler):
def get(self):
cmd = urlparse.parse_qs(self.request.body)
_commandQueue.put(cmd)
self.write(str(cmd))
def post(self):
cmd = urlparse.parse_qs(self.request.body)
_commandQueue.put(cmd)
self.write(str(cmd))
class PollHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
cmd = yield self.getCommand()
self.write(str(cmd))
@tornado.gen.coroutine
def getCommand(self):
try:
cmd = yield _commandQueue.get(
timeout=datetime.timedelta(seconds=_commandPollTimeout)
)
raise tornado.gen.Return(cmd)
except tornado.gen.TimeoutError:
raise tornado.gen.Return()
def main():
application = tornado.web.Application(
[
(r"/", HomeHandler),
(r"/add-command", AddCommandHandler),
(r"/poll", PollHandler),
],
debug=True,
template_path=os.path.join(os.path.dirname(__file__), "templates"),
static_path=os.path.join(os.path.dirname(__file__), "static"),
)
tornado.httpserver.HTTPServer(application).listen(int(os.environ.get("PORT", 5000)))
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
これは正しい方向に私を指摘しました。ここにはいくつかの小さな修正があります。それは竜巻です。キュー.Queue。あなたはコルーチンから戻ることもできないので、代わりにtornado.gen.Return(cmd)を立ち上げなければなりませんでした。ありがとう、私はとてもこだわっていた。 – OneCleverMonkey
私はあなたのコメントに応じて更新しました。 'return'はpython 3.2以降のコルーチン(ジェネレータ関数)で有効です。 – kwarunek