Я думаю, что в вашем вопросе есть несколько заблуждений, на которые нужно ответить.
Разве асинхронная задача сельдерея не должна заставить задачи работать быстрее, чем синхронные?
Как @Yugandhar указывает в своем ответе, используя что-то вроде Celery, вы добавляете дополнительные накладные расходы на обработку. Вместо того же процесса, выполняющего код, вы фактически делаете следующее:
- Клиент отправляет сообщение брокеру.
- Рабочий забирает сообщение и выполняет его.
- Ответ работника о возврате брокеру.
- Клиент получает ответ и обрабатывает его.
Как вы можете видеть, очевидно, что использование Celery связано с дополнительными издержками по сравнению с его синхронным выполнением. Из-за этого не обязательно говорить, что «асинхронная задача быстрее, чем синхронная».
Тогда возникает вопрос: зачем использовать асинхронные задачи? Если это добавляет дополнительные издержки и может замедлить выполнение, то в чем выгода? Преимущество в том, что вам не нужно ждать ответа!
Давайте возьмем ваш ApiCall()
в качестве примера. Допустим, сам вызов занимает 10 секунд для выполнения. Выполнение этого синхронно означает, что вы блокируете все, что нужно сделать до завершения вызова. Если, например, у вас есть отправка формы, которая вызывает это, это означает, что пользователь должен ждать загрузки своего браузера в течение 10 секунд, прежде чем он получит свой ответ. Это довольно плохой пользовательский опыт.
Выполняя его асинхронно в фоновом режиме, сам вызов может занять 10,01 секунды для выполнения (медленнее из-за накладных расходов), но вместо того, чтобы ждать, пока пройдут эти секунды, вы можете (если захотите) немедленно вернуть ответьте пользователю и сделайте его намного лучше.
Ожидание результатов по сравнению с обратными вызовами
Проблема с вашим примером кода состоит в том, что синхронный код и «асинхронный» код в основном делают одно и то же. Оба они ждут результатов в режиме блокировки, и вы не получите преимуществ от асинхронного выполнения.
Используя метод .get()
, вы указываете объекту AsyncResult
ожидать результатов. Это означает, что он будет блокировать (так же, как если бы вы выполняли это синхронно) что угодно, пока работник Celery не вернет ответ.
task.delay() # Async, don't await any response.
task.delay().get() # Blocks execution until response is returned.
Иногда это то, что вам нужно, но в других случаях вам не нужно ждать ответа, и вы можете завершить выполнение HTTP-запроса и вместо этого использовать обратный вызов для обработки ответа на задачу, которую вы вызвали.