0

我有处理站点上传的 nginx 上传模块,但仍需要将文件(假设每个 3-20mb)传输到我们的 cdn,并且不希望将其委托给后台作业。

在不阻止其他请求的情况下使用龙卷风执行此操作的最佳方法是什么?我可以在异步回调中执行此操作吗?

4

2 回答 2

5

您可能会发现在站点的整体架构中添加消息队列服务(例如RabbitMQ )很有用。

这将让您通过 nginx 模块完成上传,然后在 tornado 处理程序中,发布一条包含上传文件路径的消息并退出。一个单独的过程将监视这些消息并处理传输到您的 CDN。这种类型的服务对于可以离线处理的许多其他任务(发送电子邮件等)很有用。随着系统的增长,这还为您提供了一种通过将队列处理移动到单独的机器来进行扩展的机制。

我正在使用与此非常相似的架构。只需确保将您的消息消费者进程添加到supervisord或您用于管理进程的任何内容。

在实现方面,如果你在 Ubuntu 上安装 RabbitMQ 很简单:

sudo apt-get install rabbitmq-server

在带有 EPEL 存储库的 CentOS 上:

yum install rabbit-server

有许多 Python 绑定到 RabbitMQ。Pika就是其中之一,它恰好是由负责 RabbitMQ的LShift的一名员工创建的。

下面是来自 Pika repo的一些示例代码。您可以轻松想象 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
于 2009-12-23T02:13:04.410 回答
0

关于 tornado google group 的建议指向使用异步回调(记录在http://www.tornadoweb.org/documentation#non-blocking-asynchronous-requests)将文件移动到 cdn。

nginx 上传模块将文件写入磁盘,然后将描述上传的参数传递回视图。因此,该文件不在内存中,但从磁盘读取所需的时间——这将导致请求进程阻塞自身,而不是其他龙卷风进程,afaik——可以忽略不计。

也就是说,任何不需要在线处理的东西都不应该,并且应该被推迟到类似celeryd或类似的任务队列中。

于 2009-12-25T21:13:54.153 回答