我有nginx上传模块处理网站上传,但仍然需要传输文件(比方说3-20mb)到我们的cdn,而宁愿不将其委托给后台工作。
使用龙卷风执行此操作的最佳方法是什么,而不会阻止其他请求?我可以在异步回调中执行此操作吗?
答案 0 :(得分:5)
您可能会发现在网站的整体架构中添加消息排队服务非常有用,例如RabbitMQ。
这将允许您通过nginx模块完成上传,然后在tornado处理程序中发布包含上传文件路径的消息并退出。一个单独的过程将监视这些消息并处理转移到您的CDN。这种类型的服务对于可以脱机处理的许多其他任务(发送电子邮件等)非常有用。随着系统的增长,这也为您提供了一种通过将队列处理移动到单独的计算机来扩展的机制。
我使用的架构非常类似于此。只需确保将您的消息使用者流程添加到supervisord或您用于管理流程的任何内容。
在实现方面,如果你在Ubuntu上安装RabbitMQ很简单:
sudo apt-get install rabbitmq-server
在CentOS w / EPEL资料库上:
yum install rabbit-server
RabbitMQ有许多Python绑定。 Pika是其中之一,它恰好由负责RabbitMQ的employee LShift创建。
以下是Pika回购中的sample code。您可以很容易地想象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
答案 1 :(得分:0)
nginx上传模块将文件写入磁盘,然后将描述上载的参数传递回视图。因此,该文件不在内存中,但从磁盘读取所需的时间 - 这将导致请求进程阻塞自身,而不是其他龙卷风进程,afaik - 可以忽略不计。
说,任何不需要需要在线处理的东西都不应该,并且应该推迟到celeryd
或类似的任务队列。