用正确的姿势使用 celery
简介
celery
是一个简单、灵活、可靠的分布式系统,可以处理大量的消息。
celery
是一个任务队列,关注实时处理,同时支持任务调度。
它的工作机制是这样的:
快速使用
安装:pip3 install celery
# proj.py
from celery import Celery
app = Celery("hello", broker="amqp://guest@localhost//")
@app.task
def hello():
return "hello world"
启动 worker
// 启动 worker
$ celery -A proj worker -l info
-------------- celery@bogon v4.2.2 (windowlicker)
---- **** -----
--- * *** * -- macOS-10.15.1-x86_64-i386-64bit 2019-12-09 17:10:39
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: hello:0x10b4bc640
- ** ---------- .> transport: amqp://guest:**@localhost:5672//
- ** ---------- .> results: disabled://
- *** --- * --- .> concurrency: 8 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
# 标注 celery 获取的任务列表
[tasks]
. proj.hello
[2019-12-09 17:10:39,731: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2019-12-09 17:10:39,750: INFO/MainProcess] mingle: searching for neighbors
[2019-12-09 17:10:40,788: INFO/MainProcess] mingle: all alone
[2019-12-09 17:10:40,802: INFO/MainProcess] celery@bogon ready.
任务派发
>>> from proj import hello
>>> hello.delay()
<AsyncResult: 5e9ad990-4d09-4ed3-9b90-a1ff00d9020f>
任务接收
[2019-12-09 17:12:06,720: INFO/MainProcess] Received task: proj.hello[5e9ad990-4d09-4ed3-9b90-a1ff00d9020f]
[2019-12-09 17:12:06,723: INFO/ForkPoolWorker-8] Task proj.hello[5e9ad990-4d09-4ed3-9b90-a1ff00d9020f] succeeded in 0.00046249000000386786s: 'hello world'
这样就成功使用了 celery
。
异步任务&定时任务
异步任务
在一些场景中,可能会涉及到发短信、邮件和一些比较耗时的任务,我们期望用户在使用的时候没有延时的效果,我们可以这样做.
A:先增加一个发送邮件的任务
@app.task
def send_mail():
# 伪造:发送邮件
time.sleep(3) # 模拟耗时
print("Hello:xxxxx")
return 1
B:任务派发
>>> from proj import send_mail
>>> res = send_mail.delay() # 这一步不用等待,即可执行以下代码
# 查看任务状态
>>> res.status
'PENDING' # 表示任务尚未执行完成
>>> res.status
'SUCCESS' # 任务执行成功
>>> res.result # 获取任务结果,也是 return 的值
1
C:任务查看
# 接收任务
[2019-12-09 17:36:41,369: INFO/MainProcess] Received task: proj.send_mail[cb6907f1-c65a-42af-a01e-0bd7af51140f]
[2019-12-09 17:36:44,372: WARNING/ForkPoolWorker-8] Hello:xxxxx
# 执行共耗时时间及结果值
[2019-12-09 17:36:44,391: INFO/ForkPoolWorker-8] Task proj.send_mail[cb6907f1-c65a-42af-a01e-0bd7af51140f] succeeded in 3.0201863589999967s: 1
如果获取任务状态及结果报错,需要配置 celery 实例的 backend
属性,来完成任务结果的存储
定时任务
在一些场景中,比如可能需要给用户来一份生日关怀、每天发一封给自己发一封天气预报...我们可以这样做.
- 在添加定时任务的时候,需要使用到
celery beat
这样的一个调度器,由它来定期启动任务,派发给工作者去执行这些任务。 - 默认情况下,任务来自
beat_schedule
设置,但是也可以使用自定义存储,比如将任务存储在SQL数据库中。 - 要确保
celery beat
这个调度器只运行这一个,否则你可能会得到重复的任务。 - Using a centralized approach means the schedule doesn’t have to be synchronized, and the service can operate without using locks.
A:配置一个发生日关怀的任务
@app.task
def send_birthday_wish(name):
# 伪造:发送生日祝福
print(f"{name}, Happy birthday to you ~ ")
return 1
B:配置何时执行
因处于东8区,先改下时区的配置
app.conf.timezone = "Asia/Shanghai"
配置任务
# 第一种配置方式
...
from celery.schedules import crontab
...
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# 每 10s 发送一个生日祝福
sender.add_periodic_task(10.0, send_birthday_wish.s('liuzhichao'), name='add every 10')
# 每 30s 发送一个生日祝福
sender.add_periodic_task(30.0, send_birthday_wish.s('jenny'), expires=10)
# 每周一 7:30 发送一个生日祝福
sender.add_periodic_task(
crontab(hour=7, minute=30, day_of_week=1),
send_birthday_wish.s('xx'),
)
# 第二种配置方式
app.conf.beat_schedule = {
# 每 30s 发送一次生日祝福
'add-every-30-seconds': {
'task': 'proj.send_birthday_wish',
'schedule': 10.0,
'args': ('liuzhichao', )
},
# 每年 7月17号 9点30分 发送生日祝福
'add-every-year': {
'task': 'proj.send_birthday_wish',
'schedule': crontab(
minute=30, hour=9, day_of_month=17, month_of_year=7
),
'args': ('liuzhichao', )
}
}
C:启动定时任务
# 启动定时任务服务
$ celery -A proj beat
OR
# 可以通过激活 workers -B 选项将 beat 嵌入到 worker 中,如果你永远不会运行一个以上的 worker 节点,这是很方便的,但是它不常用,因此不推荐在生产中使用。
$ celery -A proj worker -B
更多的属性(HIGH API)
eta & countdown & expires
retry & ignore_result
组操作
更多参考
任务派发的三种方式
框架集成
django及定时任务的配置
其它框架集成
高可用
celery 进程挂掉
用正确的姿势使用 celery的更多相关文章
- xpath轴的正确使用姿势
网上看了许多关于轴的介绍,只介绍了语法,而没有明说具体实际中该怎么使用,百思不得其解. 背景--python中使用xpath: ----------------------------------- ...
- 高版本jquery尤其是1.10.2的版本设置input radio设置值的最正确的姿势。
$("input:radio[name="analyshowtype"]").attr("checked",false); $(" ...
- NSnotificationCenter 正确使用姿势, removeObject 探索
最近在做平板的过程中,发现了一些很不规范的代码.偶然修复支付bug的时候,看到其他项目代码,使用通知的地方没有移除,我以为我这个模块的支付闪退是因为他通知没有移除的缘故.而在debug和看了具体的代码 ...
- 微信H5中静默登录及非静默登录的正确使用姿势
在微信中打开网页且需要调用微信登录接口时,微信官方给我们提供了两种登录调用方式:静默登录和非静默登录:但是官方文档中却没有说明在何种情况下使用静默登录,何种情况下使用非静默登录,所以在这里,我想将之前 ...
- Java日志正确使用姿势
前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中“尽情”的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名 ...
- MongoDB系列:五、MongoDB Driver使用正确的姿势连接复制集
MongoDB复制集(Replica Set)通过存储多份数据副本来保证数据的高可靠,通过自动的主备切换机制来保证服务的高可用.但需要注意的时,连接副本集的姿势如果不对,服务高可用将不复存在. 使用复 ...
- 基于winserver的Apollo配置中心分布式&集群部署实践(正确部署姿势)
基于winserver的Apollo配置中心分布式&集群部署实践(正确部署姿势) 前言 前几天对Apollo配置中心的demo进行一个部署试用,现公司已决定使用,这两天进行分布式部署的时候 ...
- 玩转java多线程(wait和notifyAll的正确使用姿势)
转载请标明博客的地址 本人博客和github账号,如果对你有帮助请在本人github项目AioSocket上点个star,激励作者对社区贡献 个人博客:https://www.cnblogs.com/ ...
- Gradle的依赖方式——Lombok在Gradle中的正确配置姿势
写过java的都知道,lombok几乎在项目中处于不可或缺的一部分,但是lombok在Gradle的项目中配置并非人人都知道. 很多人在项目依赖中直接这样写 1 compile "org.p ...
随机推荐
- Linux学习笔记之秋水BBR一键部署
0x00 本脚本适用环境 系统支持:CentOS 6+,Debian 7+,Ubuntu 12+内存要求:≥128M 阅读文章时请除手动删出干扰字符“1”.(Shadowsocks) 0x01 关于本 ...
- mvc_第一章后入门_第一遍_控制器和视图
在掌握了数据库访问方法之后,我们来看几个mvc的入门程序,借此熟悉mvc的常见工作方式. 一.创建项目,显示一个最简单的页面. 要点:1.为了突出重点,不使用模版:2.项目类型为mvc,便于获得vs添 ...
- Django model distinct 的使用方法
原文: 今天突然有人问起在 django 的 model 里面怎么用 distinct, 对于这种东西,我一向的观点是查看django 的在线文档.于是不加思索的根据在线文档给出了答案,但结果很让人沮 ...
- 【转载】Jupyter Notebook 常用快捷键
原文:http://blog.csdn.net/lawme/article/details/51034543 Jupyter Notebook 有两种键盘输入模式.编辑模式,允许你往单元中键入代码或文 ...
- 【Mysql技术内幕InnoDB存储引擎】读书笔记
一.存储引擎 1.InnoDB引擎 设计目标是面向在线事务(OLTP)处理的应用. 支持事务.行级锁.通过多版本并发控制(MVCC)支持高并发.提供一致性非锁定读.next-key locking避免 ...
- zynq7020开发板+ Z-turn调试计划
参加米尔zynq7020开发板试用活动. 收到米尔z-turn板子后,焊接了一个JTAG转接板,以方便调试PL部分,对于后面的调试部分,主要分三个部分走:1.调试FPGA部分,实现逻辑控制外围简单的设 ...
- webpack 入门和常用插件的使用
常用配置参数 module.exports = { context: path.resolve(__dirname, '../'), entry: { app: './src/main.js' }, ...
- 12、微信小程序实现授权
在index.wxml中: <!--index.wxml--> <view wx:if="{{isHide}}"> <view wx:if=" ...
- JavaScript API 与 DOM
一.API 1.API 的概念 API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供引用程序与开发人员基于某软件或硬件得以访问 ...
- JavaScript 之 location 对象
一.location 对象 location 对象是 window 对象下的一个属性,使用的时候可以省略 window 对象. 常用属性: location.href = 'http://www.ba ...