Python & Celery 学习笔记_任务排程

本篇内容主要在讨论,该如何让 celery 在指定时间执行任务
过程中如果有错误,欢迎留言讨论喔 ~

一、建立 task

from celery import Celery
from setting import broker_url, backend_url
from datetime import datetime

app = Celery("celery_start", broker=broker_url, backend=backend_url)


@app.task
def get_time(name: str):
    now = datetime.now()

    return f"Hello {name} 现在时间为 {now.strftime('%Y-%m-%d, %H:%M:%S')}"

二、countdown 参数

countdown 参数单位为秒,使用这个参数可以让 celery worker 在收到任务後
过了指定单位的秒数再执行

get_time.apply_async(("nick",), countdown=20)

下图中我们可以看到 celery 在收到任务後,过了大约 20 秒才执行任务
https://ithelp.ithome.com.tw/upload/images/20220313/20144024zs6j0cxJBm.jpg

三、eta 参数

eta 参数接收的资料型态须为 datetime 物件,但要特别注意,celery 内部所接收的时间
是 UTC 标准时间,虽然说 celery 本身有提供一些 config 可以让使用者作设定,但是对
於时区的部分似乎是没有效果,因此如果要利用 eta 的话我们必须使用 pytz 这个套件对
时间做转换,下方为 pytz 的范例

from celery_schedule import get_time
from datetime import datetime, timedelta
import pytz

# 先设定时区
local_timezone = pytz.timezone("Asia/Taipei")

# 产生一笔时间物件,并计算想要甚麽时候执行任务
# 也可以直接利用 datetime 直接指定一个日期
now = datetime.now()
exec_time = now + timedelta(seconds=10)

# 利用 pytz 进行转换
exec_time = local_timezone.localize(exec_time)

# 送出任务
get_time.apply_async(("nick",), eta=exec_time)

如下图所示,可以看到大约在 10 秒钟後任务就会被 celry worker 执行
https://ithelp.ithome.com.tw/upload/images/20220313/20144024TMyHt619xX.jpg

四、expries 参数

expries 参数可以理解程,任务的到期时间,也就是这个任务最晚甚麽时候要被执行,
前面有提到,celery 可以自动将任务进行排队,由於 worker 的 process 的数量有限
如果一次送太多任务,任务就必须进行排队,因此可以透过设定这个参数来告诉 celery
,该任务最晚必须於甚麽时候执行

附注: 若 celery 收到 expries 已经过期的任务时,则 celery 会将任务状态标记为 revoke,代表不会去执行这个任务,任务状态相关的部分会於下一篇文章进行解说

附注: expries 可以接收的资料型态为 int (用於指定秒数) 以及 datetime (用於指定日期)

from celery_schedule import get_time
from datetime import datetime, timedelta
import pytz

# 先设定时区
local_timezone = pytz.timezone("Asia/Taipei")

# 产生一笔时间物件,并计算想要甚麽时候执行任务
# 也可以直接利用 datetime 直接指定一个日期
now = datetime.now()
exec_time = now + timedelta(seconds=10)

# 利用 pytz 进行转换
exec_time = local_timezone.localize(exec_time)

# 送出任务
get_time.apply_async(("nick",), expries=exec_time)

如下图所示,可以看到 celery 在收到任务後马上执行,因为版主只有送了一个任务进入列队
https://ithelp.ithome.com.tw/upload/images/20220313/201440248224kJqLfL.jpg

五、redis 重复派送任务问题

redis 对於长时间 eta 的处理不太优,常常会产生非预期的问题,例如重复派送任务等,可以看看这篇文章
若遇上此问题,可以考虑将 broker 换成 rabbitmq 或是利用 celery beat 重复检查看看是否有任务到期
若到期再用 delay 送进任务列队即可


<<:  .NET Framework4.7.2 制作 Web API 图片上传接收功能

>>:  7. STM32-结合中断来做个红绿灯吧!

Day 12 - Using List<T> to Store JSON Format Path with ASP.NET Web Forms C# 用强类型物件清单储存 JSON 格式的相簿图片路径

=x= 🌵 建立後台相簿管理并使用 JSON 格式储存多个图片的路径。 相簿管理功能介绍 : 📌 这...

前端工程师也能开发全端网页:挑战 30 天用 React 加上 Firebase 打造社群网站|Day28 留言电子邮件通知

连续 30 天不中断每天上传一支教学影片,教你如何用 React 加上 Firebase 打造社群...

产品团队调整

目前的产品团队主要是跑 Scrum 的方式,截至目前为止已经接近 100 次的 Sprint 了,从...

LeetCode 双刀流: 1. Two Sum

1. Two Sum 我们挑选 LeetCode 中的 1. Two Sum 作为我们实作练习的第...

Day 30:Deploy To GitHub Pages

在我们辛苦开发完专案後,需要找一个网路空间,把我们的网站布署上去来提供服务,因此这篇我们将使用Git...