gpt4 book ai didi

django - 为什么 Celery 异步任务比同步任务慢?

转载 作者:IT王子 更新时间:2023-10-29 06:04:15 26 4
gpt4 key购买 nike

我正在开发一个使用 Celery 异步运行某些任务的 Django 应用程序。我尝试使用 Apache Bench 执行负载测试并检查响应时间。从结果中我可以看出,没有 celery 异步任务,响应时间会更快。

我正在使用:

  • Django:2.1.0
  • celery:4.2.1
  • Redis(代理):2.10.5
  • django-redis: 4.9.0
  • Django settings.py中的 celery 配置:

    BROKER_URL = 'redis://127.0.0.1:6379/1'
    CELERY_RESULT_BACKEND = 'django-db' # Using django_celery_results
    CELERY_ACCEPT_CONTENT = ['application/json']
    CELERY_TASK_SERIALIZER = 'json'
    CELERY_RESULT_SERIALIZER = 'json'
    CELERY_TIMEZONE = 'Asia/Kolkata'

    以下是我的代码(我的系统公开的API):

    class CustomerSearch(APIView):

    def post(self, request):
    request_dict = {# Request parameters}
    # Async Block
    response = celery_search_customer_task.delay(request_dict)
    response = response.get()
    # Synchronous Block (uncomment following to make synchronous call)
    # api_obj = ApiCall(request=request_dict)
    # response = api_obj.search_customer() # this makes an API call to
    return Response(response)

    还有 tasks.py 中的 celery 任务:

    @app.task(bind=True)
    def celery_search_customer_task(self, req_data={}):
    api_obj = ApiCall(request=req_data)
    response = api_obj.search_customer() # this makes an API call to another system
    return response

    Apache 工作台命令:

    ab -p req_data.data -T application/x-www-form-urlencoded -l -r -n 10 -c 10 -k -H "Authorization: Token <my_token>" http://<my_host_name>/<api_end_point>/

    下面是ab的结果:
    没有 celery 异步任务

    Concurrency Level:      10
    Time taken for tests: 1.264 seconds
    Complete requests: 10
    Failed requests: 0
    Keep-Alive requests: 0
    Total transferred: 3960 bytes
    Total body sent: 3200
    HTML transferred: 1760 bytes
    Requests per second: 7.91 [#/sec] (mean)
    Time per request: 1264.011 [ms] (mean)
    Time per request: 126.401 [ms] (mean, across all concurrent requests)
    Transfer rate: 3.06 [Kbytes/sec] received
    2.47 kb/s sent
    5.53 kb/s total

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 259 270 10.7 266 298
    Processing: 875 928 36.9 955 967
    Waiting: 875 926 35.3 950 962
    Total: 1141 1198 43.4 1224 1263

    Percentage of the requests served within a certain time (ms)
    50% 1224
    66% 1225
    75% 1231
    80% 1233
    90% 1263
    95% 1263
    98% 1263
    99% 1263
    100% 1263 (longest request)

    使用 celery 异步任务

    Concurrency Level:      10
    Time taken for tests: 10.776 seconds
    Complete requests: 10
    Failed requests: 0
    Keep-Alive requests: 0
    Total transferred: 3960 bytes
    Total body sent: 3200
    HTML transferred: 1760 bytes
    Requests per second: 0.93 [#/sec] (mean)
    Time per request: 10775.688 [ms] (mean)
    Time per request: 1077.569 [ms] (mean, across all concurrent requests)
    Transfer rate: 0.36 [Kbytes/sec] received
    0.29 kb/s sent
    0.65 kb/s total

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 259 271 9.2 268 284
    Processing: 1132 6128 4091.9 8976 10492
    Waiting: 1132 6127 4091.3 8975 10491
    Total: 1397 6399 4099.3 9244 10775

    Percentage of the requests served within a certain time (ms)
    50% 9244
    66% 9252
    75% 10188
    80% 10196
    90% 10775
    95% 10775
    98% 10775
    99% 10775
    100% 10775 (longest request)

    celery 异步任务不是应该使任务比同步任务运行得更快吗?我可能在这里错过了什么?

    如有任何帮助,我们将不胜感激。谢谢。

    最佳答案

    我认为您的问题中存在多种误解,需要予以解答。

    Isn't celery async task supposed to make tasks work faster than synchronous tasks?

    正如@Yugandhar 在他的回答中指出的那样,通过使用 Celery 之类的东西,您正在为您的处理增加额外的开销。您实际上不是在执行代码,而是在执行以下操作:

    • 客户端向代理发送消息。
    • Worker 获取消息并执行它。
    • Worker 返回给 broker 的响应。
    • 客户端获取响应并进行处理。

    如您所见,与同步执行 Celery 相比,使用 Celery 显然会产生额外的开销。正因为如此,“异步任务比同步任务快”的说法并不一定正确。

    那么问题来了,为什么要使用异步任务呢?如果它增加了额外的开销并可能减慢执行速度,那么它有什么好处呢?好处是您无需等待响应!

    让我们以您的ApiCall() 为例。假设调用本身需要 10 秒来执行。通过同步执行它意味着您将阻止其他任何事情在调用完成之前完成。例如,如果您有一个触发此事件的表单提交,则意味着用户必须等待浏览器加载 10 秒才能收到响应。这是非常糟糕的用户体验。

    通过在后台异步执行,调用本身可能需要 10.01 秒才能执行(由于开销较慢)但不必等待这些秒过去,您可以(如果您选择)立即返回响应用户并使用户体验更好。

    等待结果与回调

    您的代码示例的问题是同步代码和“异步”代码基本上做同样的事情。它们都以阻塞方式等待结果,您并没有真正获得异步执行它的好处。

    通过使用 .get() 方法,您告诉 AsyncResult 对象等待结果。这意味着它会阻塞(就像你同步执行它一样)任何东西,直到 Celery worker 返回响应。

    task.delay()        # Async, don't await any response.
    task.delay().get() # Blocks execution until response is returned.

    有时这是您想要的,但在其他情况下您不需要等待响应,您可以完成 HTTP 请求的执行,而是使用回调来处理您触发的任务的响应。

    关于django - 为什么 Celery 异步任务比同步任务慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55466493/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com