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

标签 python django redis celery gevent

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

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

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

一些问题:

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

更新:试图进一步讨论这个问题。我在 Kombu 上做了一些阅读,它似乎能够做我想做的事情,尽管它的水平比 celery 低得多。这是我的想法的图表。 It's a simplified version, i.e. skipping the DB saving steps done by worker_2.

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

更新 2:我看到有 ability to broadcast你能把它和和弦结合起来吗?一般来说,你能把 celery 和生海带一起吃吗?这听起来像是关于冰沙的问题。

最佳答案

我会尽可能多地回答问题。

Can this (and should this) be done using celery?

是的,你可以

I'm using django. Should I try to use django-celery over plain celery?

Django 对 celery 有很好的支持,可以使开发过程中的生活更轻松

Each one of those tasks might spawn off other tasks - such as logging what just happened or other types of branching off. Is this possible?

您可以从带有 ignore_result = true 的任务开始子任务,只有副作用

Could tasks be returning the data they get - i.e. potentially Kb of data through celery (redis as underlying in this case) or should they write to the DB, and just pass pointers to that data around?

我建议将结果放在数据库中,然后传递 id 会让您的经纪人和工作人员满意。更少的数据传输/酸洗等

Each task is mostly I/O bound, and was initially just going to use gevent from the web thread to fan out the requests and skip the whole queuing design, but it turns out that it would be reused for a different component. Trying to keep the whole round trip through the Qs real time will probably require many workers making sure the queueus are mostly empty. Or is it? Would running the gevent worker pool help with this?

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

Do I have to write gevent specific tasks or will using the gevent pool deal with network IO automagically?

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

Is it possible to assign priority to certain tasks?

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

What about keeping them in order?

链条是维持秩序的一种方式。和弦是总结的好方法。 Celery 会处理它,因此您不必担心。即使在使用 gevent 池时,最终也可以推断出任务执行的顺序。

Should I skip celery and just use kombu?

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

It seems like celery is geared more towards "tasks" that can be deferred and are not time sensitive.

Celery 也支持定时任务。如果这就是您所说的意思。

Am I nuts for trying to keep this real time?

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

What other technologies should I look at?

关于 celery ,你应该明智地选择结果存储。我的建议是使用 Cassandra 。它适用于实时数据(写入和查询方面)。您也可以使用 redis 或 mongodb。他们将自己的一组问题作为结果存储。但是随后对配置进行一些微调可能会有很长的路要走。

如果您的意思与 celery 完全不同,那么您可以查看 asyncio (python3.5) 和 zeromq 以实现相同的目的。不过我不能对此发表更多评论。

关于python - 使用 Celery 与 Gevent 进行实时、同步的外部 API 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16328341/

相关文章:

python - argparse - 禁止出现相同的参数

python - 自定义 django-admin 模板

javascript - 为什么我会收到 'CSRF token missing or incorrect' 错误?

mysql - 如何频繁同步市场数据并显示为历史时间序列数据

java - 存储大量套接字的最佳做法是什么?

php - ob_start() 未能在 laravel 3 中创建缓冲区

Python Django 错误 : version GLIBC_PRIVATE not defined

python - 将平均列添加到 Pandas 多索引数据框中

python - 单击项目 View 的空白区域时清除选择

python - 在 django 中按数字字符串排序查询结果(postgres 后端)