我应该对轮询其他API的API使用任务队列(Celery),ayncio还是都不使用?

时间:2019-02-28 11:43:42

标签: django celery api-design task-queue

我已经使用Django编写了一个API,其目的是充当网站后端与我们使用的外部服务之间的桥梁,因此该网站不必处理对外部API的许多请求(CRM,日历事件,电子邮件提供商等。

API主要轮询其他服务,解析结果并将其转发到网站后端。

最初,我去了一个基于Celery的任务队列,因为在我看来,它是将处理任务转移到另一个实例的正确工具,但我开始认为它确实不符合目的。

由于网站希望同步响应,所以我的代码包含很多:

results = my_task.delay().get()

results = chain(fetch_results.s(), parse_results.s()).delay().get()

使用Celery任务感觉不正确。

当拉取数十个请求并并行处理结果时(例如定期执行 refresh 任务),效率很高,但是对于简单请求(获取-解析-转发)会增加很多开销,代表大部分流量。

对于那些“简单请求”,我应该完全同步,并在特定情况下保留Celery任务吗?是否有其他设计(可能涉及asyncio)更适合我的API的目的?


在EBS EC2实例上使用Django,Celery(带有Amazon SQS)。

1 个答案:

答案 0 :(得分:5)

您可以考虑在您的Django网络服务器上使用Gevent,以使其针对您提到的“简单请求”有效运行,而不会受到阻碍。如果继续使用这种方法,请确保使用PgBouncer或Pgpool-II或Python库来池化数据库连接,因为每个greenlet都会建立自己的连接。

一旦实现,就可以使用Gevent代替Celery通过连接多个Greenlet来处理异步处理,每个Greenlet都发出外部API请求,而不会产生将消息传递给外部celery worker的开销。

您的实现类似于我们在Kloudless所做的实现,它提供了一个API来访问其他多个API,包括CRM,日历,存储等。