【发布时间】:2013-04-26 01:15:47
【问题描述】:
我正在开发一个 Web 应用程序,该应用程序将接收来自用户的请求,并且必须点击多个外部 API 来组合该请求的答案。这可以直接从主网络线程使用 gevent 之类的东西来扇出请求来完成。
另外,我在想,我可以将传入的请求放入队列并使用工作人员来分配负载。这个想法是尽量保持实时,同时将请求分配给几个工作人员。这些工作人员中的每一个都将只查询众多外部 API 中的一个。然后,他们收到的响应将经过一系列转换,保存到数据库中,转换为通用模式并保存在通用数据库中,最终组合成一个大响应,该响应将通过 Web 请求返回。 Web 请求很可能一直被阻塞,用户在等待,所以保持 尽可能快的排队和出队很重要。
外部 API 调用可以轻松转换为单独的任务。我认为链接 从一个 api 任务到转换为数据库保存任务可以使用链等来完成,最终结果将所有结果组合在一起使用和弦返回到 web 线程。
一些问题:
- 这可以(并且应该)用芹菜来完成吗?
- 我正在使用 django。我应该尝试在普通芹菜上使用 django-celery 吗?
- 这些任务中的每一项都可能衍生出其他任务 - 例如记录刚刚记录的内容 发生或其他类型的分支。这可能吗?
- 任务是否可以返回他们获得的数据 - 即可能通过 celery(在本例中为 redis 作为底层)的 Kb 数据,或者他们应该写入数据库,然后只传递指向该数据的指针?
- 每个任务主要是 I/O 绑定的,最初只是要使用来自 Web 线程的 gevent 来扇出请求并跳过整个队列设计,但事实证明它将被重用于不同的组件。试图通过 Qs 实时保持整个往返行程可能需要许多工作人员确保队列大部分是空的。或者是吗?运行 gevent 工作程序池会对此有所帮助吗?
- 我必须编写 gevent 特定任务还是使用 gevent 池自动处理网络 IO?
- 是否可以为某些任务分配优先级?
- 如何保持它们井井有条?
- 我应该跳过芹菜而只使用昆布吗?
- 似乎 celery 更适合于可以推迟的“任务” 对时间不敏感。我是不是想保持这个实时性?
- 我还应该考虑哪些其他技术?
更新:试图进一步解决这个问题。我在 Kombu 上做了一些阅读,它似乎能够做我想做的事,尽管水平比 celery 低得多。这是我想到的图表。
使用 Kombu 可访问的原始队列似乎可以实现许多工作人员订阅广播消息的能力。如果使用队列,则发布者不需要知道类型和编号。可以使用 Celery 实现类似的功能吗?似乎如果你想制作和弦,你需要在运行时知道和弦中将涉及哪些任务,而在这种情况下,你可以简单地将听众添加到广播中,并简单地确保他们宣布他们在运行以将响应添加到最终队列。
更新 2:我看到有 ability to broadcast 你能把它和和弦结合起来吗?一般来说,你能把芹菜和生海带结合起来吗?这听起来像是一个关于冰沙的问题。
【问题讨论】:
-
我个人会使用 rabbitMQ + kombu 来解决这个问题。最好为将由多个线程处理的事件设置侦听器,最后在收集所有数据后发送响应。它通常听起来像是一个事件驱动的架构,并且包含一些好的队列/观察者机制是内在的。
-
哦!当然 - 如果应用程序很小并且没有多个层,您可以在 Python-twisted 中实现它,这对于从自身发出所有这些阻塞请求非常有用。
-
@wojciechz 感谢您的建议。我一直在研究 Kombu。看来 Kombu 的扇出交换将是我正在寻找的。是否有可能将它与在另一边工作的 celery 应用程序/任务结合起来?
-
坦率地说 - 我不知道。但只要我们在谈论编写软件的和平 - 是的 - 这是可能的:)
-
你是怎么解决这个问题的?
标签: python django redis celery gevent