【发布时间】:2013-01-24 18:49:11
【问题描述】:
在我的 Django Web 应用程序中,我有一个工作程序,它是一个限速 API 的客户端,负责处理从我的服务器线程到该 API 的所有请求。我使用我的数据库来存储任务队列。任务可以大量出现,也可以根本没有。我正在使用事件循环来轮询队列并管理任务之间的延迟,以防超出速率限制(限制是动态的)。这一切都很好,但我唯一想做的另一件事是让工作人员在队列变干时停止访问数据库,以及让我的 Django 应用程序向工作人员发出队列不再存在的信号再次干燥。
从示意图上看,在伪 Python 中它看起来像这样:
state = NORMAL
delay_time = NORMAL_DELAY
while True:
sleep(delay_time)
if state == DORMANT:
continue
task = get_next_task() # hits database
if task is None:
state = DORMANT
delay_time = NORMAL_TIME
try:
execute(task)
except RateExceeded:
delay_time = backoff(delay_time)
else:
delay_time = NORMAL_DELAY
# Triggered by web layer
def asynchronous_event():
state = NORMAL
我要么想要一个从 Web 层触发的异步事件,该事件可以将状态设置回 NORMAL(将在 sleep 期间执行),要么想要一些不会添加不必要的循环数据库查询的其他轻量级检查。
在单机设置中,我可以只使用信号,但显然这在多机设置中不起作用。我试图不必仅仅为了这个信号而运行单独的消息队列服务器。我托管在 Dotcloud 上,以防万一基于网络的解决方案起作用。理想情况下,在易于实现方面或多或少等同于信号处理程序。我已经研究过 ZeroRPC,但我不确定如何将它合并到我的事件循环中。
有什么想法吗?
编辑
我正在研究 ZeroMQ 来解决这个问题,但我需要一些帮助。棘手的部分是会有多个并发的网络服务器实例,并且在重新部署时,我需要从一个工作人员平稳过渡到其继任者。所以,请耐心等待,因为我的术语可能不正确,在我看来,最好的办法是让每个工作人员异步绑定到作为邮箱的地址,在主循环中检查以从休眠模式唤醒.每个工作人员在其 IP 的数据库中创建一条记录,并带有创建日期的时间戳。提交请求时,Web 服务器会向所有工作人员发布消息。当一个worker接收到一条消息时,它会检查它的worker是否具有最新的创建日期:如果是,它会处理该消息,如果不是,它会自行终止。
这似乎很麻烦,但我想把它做好,因为我可能会在我的应用程序的其他地方使用这个范例。
【问题讨论】:
-
如果您已经在使用 Redis,您可以将其用作轻量级队列。这会将它从数据库中一起删除,而且速度非常快。
-
听起来不错,但我还没有使用 Redis。如果这是唯一不错的选择,我可能只好忍气吞声了。
-
如果您正在查看 ZeroMQ 并且正在使用 Python,您应该查看 ZeroRPC。它有助于抽象出很多 ZeroMQ 复杂性。
-
糟糕,刚刚注意到您已经查看了 ZeroRPC。很抱歉没有仔细关注。
-
可能有一种方法,向 dotcloud 提交支持票证,这可能是获得答案的最佳选择。
标签: django asynchronous signals message-queue dotcloud