7

だから私は以下のハンドラーを持っています:

class PublishHandler(BaseHandler):

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

私が直面している問題は、some_function()の実行に時間がかかることです。また、呼び出し時にpostリクエストをすぐに返し、可能であればsome_function()を別のスレッド/プロセスで実行したいと考えています。

私はデータベースとしてberkeleydbを使用していますが、私がやろうとしていることは比較的単純です。

それぞれにフィルターがあるユーザーのデータベースがあります。フィルタがメッセージと一致する場合、サーバーはメッセージをユーザーに送信します。現在、私は数千人のユーザーでテストしているため、POSTリクエストを介してメッセージを公開するたびに、数千人のユーザーを繰り返して一致するものを見つけます。これは、物事を行うための私の素朴な実装であり、したがって私の質問です。どうすればこれを改善できますか?

4

2 に答える 2

7

IOLoopadd_callbackメソッドを次のように使用することで、これを達成できる場合があります。

loop.add_callback(lambda: some_function(message))

Tornado は次の IOLoop パスでコールバックを実行します。これにより、コードが実行される前にリクエストが完了する可能性があります(確実に知るには、Tornado の内臓を掘り下げるか、テストする必要があります)。

欠点は、作成した実行時間の長いコードの実行にはまだ時間がかかり、別のリクエストがブロックされる可能性があることです。これらのリクエストが一度に大量に届く場合、これは理想的ではありません。

より確実な解決策は、別のスレッドまたはプロセスで実行することです。Python での最善の方法は、GIL のためにプロセスを使用することです (慣れていない場合は、プロセスを読むことを強くお勧めします)。ただし、シングル プロセッサ マシンでは、スレッド化された実装でも問題なく動作し、実装がより簡単になる場合があります。

スレッド ルートを使用する場合は、ミューテックス、スレッド、およびキューを使用して、優れた「非同期エグゼキュータ」モジュールを構築できます。multiprocessing別のプロセスを使用するルートに進みたい場合は、モジュールを確認してください。

于 2010-10-06T04:42:22.820 に答える
1

私はこれを試しましたが、コールバックが呼び出される前にリクエストが完了しないと思います。

汚いハックは、2つのレベルのadd_callbackを呼び出すことだと思います。例:

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

しかし、これらはせいぜいハックです。私は今より良い解決策を探しています、おそらくいくつかのメッセージキューまたは単純なスレッド解決策で終わるでしょう。

于 2010-12-09T02:35:57.220 に答える