You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Celery处理IO密集型任务比同步方式快得多?

关于Celery并发任务远快于同步请求的疑问

我正在学习Python并发编程,用Celery执行脚本发起50次请求仅耗时约0.13秒,这让我非常惊讶!而用常规同步编程完成同样操作则需要约1分钟。

我知道Celery会生成进程池执行任务,但搞不懂为什么Celery执行50次任务的速度会比同步执行单次任务还快这么多。

同步代码示例

# sync.py
import json
import requests
from timer import Timer

URL = 'https://httpbin.org/uuid'

def fetch(url):
    response = requests.get(url)
    data = json.loads(response.text)
    print(data['uuid'])


def main():
    with Timer():
        for _ in range(1):
            fetch(URL)

main()
# take ~50 seconds

Celery异步代码示例

# celery_demo.py
from celery import Celery
from timer import Timer
import json
import requests

URL = 'https://httpbin.org/uuid'

BROKER_URL = 'redis://localhost:6379/0'
RESULT_BACKEND = 'redis://localhost:6379/0'

app = Celery(__name__, broker=BROKER_URL, backend=RESULT_BACKEND)


@app.task(name='fetch')
def fetch():
    res = requests.get(URL)
    return res.json()['uuid']


def main():
    with Timer():
        for i in range(50):
            res = fetch.delay()
            print(res)


if __name__ == '__main__':
    main()

# Celery configuration
# celery -A celery_demo.app worker --concurrency=4

# takes ~0.1 to 0.2 seconds

原因解析

  • 计时范围的核心差异:同步代码里的Timer包裹了单次请求的完整流程——从发起请求、等待服务器响应,到接收数据、解析输出,统计的是请求真实的全程耗时;而Celery代码里的Timer只统计了把任务提交到消息队列的过程,fetch.delay()只是向worker发送任务指令后立刻返回任务ID,真正的请求执行、等待响应等操作都是在后台worker中异步进行的,这部分时间完全没被Timer算进去。

  • 并发执行的真实逻辑:你配置的Celery worker开启了4个并发进程,能同时处理多个请求。但当前的计时并没有体现并发执行的实际耗时,如果你修改代码,等待所有Celery任务执行完成后再结束Timer(比如用res.get()逐个等待结果,或者用group批量提交后统一等待),统计出的时间会比单次同步请求长,但肯定远低于50次同步请求的总耗时——因为并发可以让多个请求同时处于网络等待状态,CPU不用空等,能高效利用资源。

  • 网络请求的IO特性:网络请求的大部分时间都花在等待服务器响应(IO等待),同步代码只能串行等待,而Celery的并发模式可以把这些等待时间重叠起来,自然整体效率会大幅提升,但你当前的测试没有捕捉到这个真实效率,只是测了任务提交的速度。

内容的提问来源于stack exchange,提问作者Quoc-Hung Hoang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:44:59