使用 Celery 使用 Gevent 进行实时、同步的外部 API 查询

And*_*res 6 python django redis celery gevent

我正在开发一个 Web 应用程序,该应用程序将接收来自用户的请求,并且必须访问许多外部 API 来编写该请求的答案。这可以直接从主 Web 线程使用 gevent 之类的东西来扇出请求。

或者,我在想,我可以将传入的请求放入队列并使用工作人员来分配负载。我们的想法是尽量保持实时性,同时在几个工作人员之间拆分请求。这些工作人员中的每一个都将只查询许多外部 API 中的一个。然后他们收到的响应将经过一系列转换,保存到数据库中,转换为公共模式并保存在公共数据库中,最终组合成一个大响应,通过 Web 请求返回。Web 请求很可能会一直阻塞,用户在等待,因此尽可能快地保持排队和出队很重要。

外部 API 调用可以轻松转换为单独的任务。我认为可以使用链等来完成从一个 api 任务到转换为 DB 保存任务的链接,并且最终结果组合使用和弦返回到 web 线程的所有结果。

一些问题:

  • 可以(并且应该这样做)使用芹菜来完成吗?
  • 我正在使用 Django。我应该尝试在普通芹菜上使用 django-celery 吗?
  • 这些任务中的每一个都可能衍生出其他任务——例如记录刚刚发生的事情或其他类型的分支。这可能吗?
  • 任务是否可以返回他们获得的数据——即可能通过 celery 返回 Kb 的数据(在这种情况下,redis 作为底层),还是应该写入数据库,然后只传递指向该数据的指针?
  • 每个任务主要是 I/O 绑定的,并且最初只是要使用来自 Web 线程的 gevent 来扇出请求并跳过整个排队设计,但事实证明它将被重用于不同的组件。试图通过 Qs 实时保持整个往返行程可能需要许多工作人员确保队列大部分是空的。或者是吗?运行 gevent 工作池会对此有帮助吗?
  • 我是否必须编写特定于 gevent 的任务,还是会使用 gevent 池自动处理网络 IO?
  • 是否可以为某些任务分配优先级?
  • 让他们保持秩序怎么样?
  • 我应该跳过芹菜而只使用kombu吗?
  • 似乎芹菜更适合可以推迟并且对时间不敏感的“任务”。我是否因为试图保持这种实时性而发疯?
  • 我还应该关注哪些其他技术?

更新:尝试更详细地解决这个问题。我在 Kombu 上做了一些阅读,它似乎能够做我想做的事,尽管比 celery 低得多。这是我想到的图表。这是一个简化版本,即跳过由worker_2 完成的数据库保存步骤。

使用 Kombu 访问原始队列似乎可能是许多工作人员订阅广播消息的能力。如果使用队列,发布者不需要知道类型和数量。使用 Celery 可以实现类似的功能吗?似乎如果你想制作一个和弦,你需要在运行时知道和弦中将涉及哪些任务,而在这种情况下,你可以简单地向广播添加监听器,并确保他们宣布他们在运行以将响应添加到最终队列。

更新2:我看到有广播能力你能把它和和弦结合起来吗?一般来说,你能把芹菜和生海带混合吗?这听起来像是一个关于冰沙的问题。

Ars*_*ari 5

我将尽力回答尽可能多的问题。

这可以(并且应该)使用芹菜来完成吗?

是的你可以

我正在使用 django。我应该尝试使用 django-celery 而不是普通芹菜吗?

Django 对 celery 有很好的支持,可以让开发过程变得更加轻松

这些任务中的每一项都可能衍生出其他任务 - 例如记录刚刚发生的事情或其他类型的分支。这可能吗?

您可以使用ignore_result = true从任务中启动子任务,仅产生副作用

任务是否可以返回它们获得的数据 - 即通过 celery(在本例中为底层的 redis)可能返回 Kb 的数据,或者它们应该写入数据库,然后只传递指向该数据的指针?

我建议将结果放入数据库,然后传递 id 会让您的经纪人和工作人员感到高兴。减少数据传输/酸洗等。

每个任务主要受 I/O 限制,最初只是要使用 Web 线程中的 gevent 来扇出请求并跳过整个排队设计,但事实证明它将被重用于不同的组件。试图保持 Q 的整个往返过程是实时的,可能需要许多工作人员来确保队列大部分是空的。或者是吗?运行 gevent 工作池对此有帮助吗?

由于进程是 io 绑定的,那么 gevent 肯定会在这里提供帮助。然而,gevent pool'd worker 的并发性应该是多少,这也是我正在寻找答案的问题。

我是否必须编写 gevent 特定任务,或者使用 gevent 池自动处理网络 IO?

当您在池中使用 Gevent 时,它会自动进行猴子修补。但是您使用的库应该能够与 gevent 很好地配合。否则,如果您使用 simplejson (用 c 编写)解析一些数据,那么这将阻止其他 gevent greenlet。

是否可以为某些任务分配优先级?

您不能为某些任务分配特定的优先级,而是将它们路由到不同的队列,然后让不同数量的工作人员监听这些队列。特定队列的工作人员越多,该队列上任务的优先级就越高。

让它们保持秩序怎么样?

连锁是维持秩序的一种方式。和弦是一个很好的总结方式。Celery 会照顾它,所以你不必担心。即使使用 gevent 池,最终也可以推断任务执行的顺序。

我应该跳过芹菜而只使用昆布吗?

如果您的用例不会随着时间的推移而变得更复杂,并且您愿意自己通过 celeryd +supervisord 管理您的流程,那么您可以。另外,如果你不关心celerymon、flower等工具自带的任务监控。

芹菜似乎更适合可以推迟且对时间不敏感的“任务”。

Celery 也支持计划任务。如果这就是你那句话的意思。

我为了保持实时性而疯了吗?

我不这么认为。只要你的消费者足够快,它就会像实时一样好。

我还应该关注哪些其他技术?

对于芹菜,您应该明智地选择结果存储。我的建议是使用 cassandra。它对于实时数据(写入和查询方面)都有好处。您还可以使用 redis 或 mongodb。他们在结果存储方面有自己的一系列问题。但配置上的一些调整可能会大有帮助。

如果您的意思与 celery 完全不同,那么您可以研究 asyncio (python3.5) 和 Zeromq 来实现相同的目的。但我无法对此发表更多评论。