Python Tornado-非同期機能が機能し続けている間にすぐにポストを返す
質問
だから私は以下にハンドラーを持っています:
class PublishHandler(BaseHandler):
def post(self):
message = self.get_argument("message")
some_function(message)
self.write("success")
私が直面している問題は、some_function()が実行に時間がかかることです。また、可能であれば、別のスレッド/プロセスでsome_function()を呼び出したときにすぐに返送したいと思います。
私はデータベースとしてBerkeley DBを使用していますが、私がやろうとしていることは比較的簡単です。
私はそれぞれフィルターを使用してユーザーのデータベースを持っています。フィルターがメッセージに一致する場合、サーバーはメッセージをユーザーに送信します。現在、私は何千人ものユーザーとテストしているので、投稿リクエストを介してメッセージを公開するたびに、数千人のユーザーを介して試合を見つけることができます。これは、物事を行うという私の素朴な実装であり、したがって私の質問です。どうすればこれをうまく行うことができますか?
解決
あなたはあなたを使うことによってこれを達成できるかもしれません IOLoop
's add_callback
SOのような方法:
loop.add_callback(lambda: some_function(message))
Tornadoは次のioloopパスでコールバックを実行します。 五月 (私は確実に知るために竜巻の勇気を掘り下げる必要があります。または、代わりにそれをテストする必要があります)そのコードが実行される前に、リクエストを完了することを許可します。
欠点は、あなたが書いた長期にわたるコードがまだ実行に時間がかかることであり、これが別の要求をブロックすることになる可能性があることです。これらのリクエストの多くが一度に入ってくる場合、それは理想的ではありません。
より完全なソリューションは、別のスレッドまたはプロセスで実行することです。 一番 Pythonの方法は、ギルのためにプロセスを使用することです(あなたがそれに慣れていないなら、それを読むことを強くお勧めします)。ただし、シングルプロセッサマシンでは、スレッドの実装も同様に機能し、実装が簡単になる場合があります。
スレッドルートに行く場合は、ミューテックス、スレッド、キューを備えた素敵な「Asyncエグゼクタ」モジュールを構築できます。をチェックしてください multiprocessing
モジュール別のプロセスを使用するルートに進みたい場合。
他のヒント
私はこれを試しましたが、コールバックが呼び出される前にリクエストが完了しないと思います。
汚いハックは、2つのレベルのadd_callbackを呼び出すことだと思います。
def get(self):
...
def _defered():
ioloop.add_callback(<whatever you want>)
ioloop.add_callback(_defered)
...
しかし、これらはせいぜいハッキングです。私は今、より良いソリューションを探していますが、おそらくメッセージキューまたはシンプルなスレッドソリューションになってしまうでしょう。