1

在我的 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接收到一条消息时,它会检查它是否具有最新的创建日期:如果是,它会处理该消息,如果不是,它会自行终止。

这似乎很麻烦,但我想把它做好,因为我可能会在我的应用程序的其他地方使用这个范例。

4

2 回答 2

0

delay_time如果数据库中没有任务,如何对工作者作业应用指数退避?这可能会为您减少足够多的数据库负载,而无需将消息从 Web 应用程序传输到工作作业的额外复杂性。就像是:

delay_time = NORMAL_DELAY

while True:
    sleep(delay_time)
    task = get_next_task() # hits database

    if task:
        try:
            execute(task)
        except RateExceeded:
            pass
        else:
            delay_time = NORMAL_DELAY
            continue

     delay_time = backoff(delay_time)
于 2013-01-24T20:02:35.040 回答
0

事实证明,我决定每次循环都访问数据库。但我也决定,如果我想努力让这变得真正高效,ZeroMQ 是我的必经之路。以下是它的工作原理:

每个工作人员绑定一个 ZeroMQ 订阅者套接字并将自己注册到工作人员数据库中,该数据库包含套接字的 IP 地址和端口。网络线程DO_TASK向最近注册的工作人员发布消息,并向QUIT可能正在工作的任何其他人发布消息。

我在 Dotcloud 上进行部署,他们的支持说使用自定义服务环境变量和构建选项可以让我打开必要的端口并获取工作任务实例的 IP。

于 2013-02-02T05:46:21.360 回答