サイトのアップロードを処理するnginxアップロードモジュールがありますが、ファイル(たとえば、それぞれ3〜20 MB)をcdnに転送する必要があり、バックグラウンドジョブに委任したくありません。
他のリクエストをブロックせずにトルネードでこれを行うための最良の方法は何ですか?非同期コールバックでこれを行うことはできますか?
サイトのアーキテクチャ全体で、RabbitMQなどのメッセージキューサービスを追加すると便利な場合があります。
これにより、nginxモジュールを介してアップロードを完了し、tornadoハンドラーで、アップロードされたファイルパスを含むメッセージを投稿して終了します。別のプロセスがこれらのメッセージを監視し、CDNへの転送を処理します。このタイプのサービスは、オフラインで処理できる他の多くのタスク(電子メールの送信など)に役立ちます。システムが成長するにつれて、これはキュー処理を別々のマシンに移動することによって拡張するメカニズムも提供します。
私はこれに非常に似たアーキテクチャを使用しています。メッセージコンシューマプロセスを、監視対象またはプロセスの管理に使用しているものに必ず追加してください。
実装に関しては、Ubuntuを使用している場合、RabbitMQのインストールは簡単です。
sudo apt-get install rabbitmq-server
CentOS w / EPELリポジトリの場合:
yum install rabbit-server
RabbitMQへのPythonバインディングは多数あります。Pikaはその1つであり、RabbitMQを担当するLShiftの従業員によって作成されています。
以下は、Pikaリポジトリからのサンプルコードのビットです。handle_deliveryメソッドがファイルパスを含むメッセージを受け入れてCDNにプッシュする方法を簡単に想像できます。
import sys
import pika
import asyncore
conn = pika.AsyncoreConnection(pika.ConnectionParameters(
sys.argv[1] if len(sys.argv) > 1 else '127.0.0.1',
credentials = pika.PlainCredentials('guest', 'guest')))
print 'Connected to %r' % (conn.server_properties,)
ch = conn.channel()
ch.queue_declare(queue="test", durable=True, exclusive=False, auto_delete=False)
should_quit = False
def handle_delivery(ch, method, header, body):
print "method=%r" % (method,)
print "header=%r" % (header,)
print " body=%r" % (body,)
ch.basic_ack(delivery_tag = method.delivery_tag)
global should_quit
should_quit = True
tag = ch.basic_consume(handle_delivery, queue = 'test')
while conn.is_alive() and not should_quit:
asyncore.loop(count = 1)
if conn.is_alive():
ch.basic_cancel(tag)
conn.close()
print conn.connection_close
tornado googleグループに関するアドバイスは、非同期コールバック(http://www.tornadoweb.org/documentation#non-blocking-asynchronous-requestsに記載)を使用してファイルをcdnに移動することを示しています。
nginxアップロードモジュールはファイルをディスクに書き込み、アップロードを説明するパラメーターをビューに戻します。したがって、ファイルはメモリ内にありませんが、ディスクからの読み取りにかかる時間(要求プロセスはそれ自体をブロックしますが、他のトルネードプロセスはafaikをブロックしません)はごくわずかです。
とは言うものの、オンラインで処理する必要のないものはすべて処理する必要はなく、同様のタスクキューに延期する必要がありますceleryd
。