异步消息队列,也能用于定时和周期性任务。每次修改的task代码还要重启worker,这个有点麻烦

所有带task()装饰器的可调用对象(usertask)都是celery.app.task.Task类的子类,也就是说task()装饰器会将usertask标识符变成Task子类的引用。

另外,celery允许用自定义Task类,不过该类要继承于celery.app.task.Task,Task类在task状态转换动作时提供了接口,如任务执行失败时调用接口on_failure,

这样就非常方便我们在自定义Task类中重定义。见http://docs.celeryproject.org/en/latest/userguide/tasks.html#custom-task-classes

task()装饰器可以接收很多参数,比如序列化类、是否保存task结果、所使用的back_end等等,见

http://docs.celeryproject.org/en/latest/userguide/tasks.html#list-of-options。比如,我们可以设置只在出错的情况下保存运行结果。即

ignore_result=False且store_errors_even_if_ignored=True,不过,ignore_result可以在全局配置文件中设置CELERY_IGNORE_RESULT

当发异步消息时调用usertask.delay()或usertask.apply_async(),它其实是将usertask的信息,如名称,入参,id等序列化后保存在broker中。

如果不限制task的处理速度,那应该设置CELERY_DISABLE_RATE_LIMITS = True,这算是celery的优化部分

task不要嵌套,如果希望多个task顺序执行(同步),那可以用回调函数,在celery中是用chain()方法实现,见

http://docs.celeryproject.org/en/latest/userguide/tasks.html#avoid-launching-synchronous-subtasks

http://docs.celeryproject.org/en/latest/userguide/canvas.html

celery在两个地方有retry,一个是在task的代码执行过程中出现异常时可以retry,不过这个需要用户在task代码中自己写,如果想

retry那就要我们自己捕获异常,并抛出Retry exception,参见http://docs.celeryproject.org/en/latest/userguide/tasks.html#retrying

另外一个地方是在调用delay()/apply_async()时,这个retry可能是指向rabbitmq发送消息时如果失败,可以重试如果想链式调用task,那要设置link参数,见

http://docs.celeryproject.org/en/latest/userguide/canvas.html#callbacks

http://docs.celeryproject.org/en/latest/userguide/canvas.html#the-primitives

开发环境中,work的启动、结束、重启可以用celery multi xxx命令

生产环境中,用http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#daemonizing

celery中的一个worker其实是代表一个进程池,一个进程池是由一个父进程和多个子进程组成, 貌似父进程不干事,只用于分配task,子进程数默认是CPU核数

一台主机上可以启多个worker,但这种方法貌似和一个worker中启多个子进程区别不大啊,两种方式都是多进程。

在启动worker时,可以设置worker的很多参数,如是否允许自动伸缩pool的容量,最大和最小容量,见

http://docs.celeryproject.org/en/latest/userguide/workers.html#autoscaling

celery有很多设置,其中在配置文件celeryconfig中的设置是全局的,另外,我们还可以单独设置task(可以在task定义的地方,也可以在delay(), apply_async()中设置),

worker启动时可以设置参数

celery的broker中的task队列可以有多个,用不同的名字命名,还可以有不同的优先级。我们启动worker时可以设置该worker只处理指定队列的task

celery中的log使用的是python的log模块,是线程安全的,而不是进程安全的。我们可以给一个worker中的每个process定义其logfile,见

http://docs.celeryproject.org/en/latest/userguide/workers.html#variables-in-file-paths

一个node是指一个worker

celery的每个worker的每个进程可以一次从broker中取出多个task

查看所有node中的活动的task: celery -A proj inspect active

查看所有node中注册的所有task:celery -A proj inspect registered

查看所有node的信息:celery -A proj inspect stats

调用异步消息接口delay() ,apply_async()时,其实只是应用程序与broker通信而已,发消息给broker,消息中包含调用的task名称,参数等,broker收到后保存。这个过程中不会与celery worker打交道

因此,这个时候即使没有启动celery worker也没有任何关系。当celery worker启动后,会主动连接broker,并从broker那里取数据来consume。同理,我们可以在任何平滑停止celery worker,而不用管

broker中是否还有没consume的消息,当celery worker重启后,它会继续处理broker中的消息。这里的启动顺序貌似只能是先启动broker,再启动celery,因为启动celery时会与broker建立连接,broker

是被动连接的。

broker自己应该是有办法保证一个消息只能被一个worker取走,而不会同时被两个worker取走。

有一个问题:rabbitmq有内存占用限制吗?如果有,那当达到这个限制时,新来的消息怎么处理?像reddis那样把旧的消息写到磁盘?还是直接抛弃旧的消息?或不再接收新消息?

Rabbitmq有监控,默认的,Rabbitmq_management是关闭的,需要打开,执行sudo rabbitmq-plugins enable rabbitmq_management,打开这个plugin,

然后重启Rabbitmq,在浏览器输入http://localhost:15672,用户名和密码都是guest,就可以看到Rabbitmq的监控信息了。

Rabbitmq相当于一个邮箱,用于接收和发送消息,而且它里面有很多队列,发送消息时可以指定用哪个队列,一个消息中包含一个task

(1) 发送者将消息发给rabbitmq的指定队列,消息中包含消息处理函数

(2) rabbitmq接收并保存消息(无数量限制)

(3) 接收者联系rabbitmq,从队列中取走消息(可以指定接收者只消费某个指定队列的消息)

(4) 接收者取回消息后,调用消息中的处理函数处理消息

其实这个过程中我们要考虑消息执行的可靠性。

第一点:若消息被worker接收后,处理过程中worker死掉了怎么办?Rabbitmq考虑到了这点,在默认情况下(是一个配置项,我们可以修改),每个消息其实是被worker拷贝了一份取走的,

当然被拷贝的消息会打上标记,当worker处理完消息后会给Rabbitmq一个确认(acknowledgment),Rabbitmq收到确认后才删除消息,这个过程没有限定超时时间,只有当worker与

Rabbitmq之间的TCP连接断开后(Rabbitmq应该是会检测worker的心跳),Rabbitmq才会将没有确认的消息重新加入到队列。我们可以使用命令:rabbitmqctl list_queues name messages_ready

messages_unacknowledged来查看有多少消息没有收到确认。它是一个默认项,我们关闭这个可靠性设置,这样,消息处理完不用再给Rabbitmq发acknowledgment了。在celery配置文件中

对应于CELERY_ACKS_LATE项

第二点:若Rabbitmq挂掉,消息也会丢失。因为要做消息的持久化,Rabbitmq这样做了,不过它的持久化并不绝对可靠,因为从接收到消息到持久化之间有时间间隔,如果想绝对可靠,见

http://www.rabbitmq.com/tutorials/tutorial-two-python.html中的Note on message persistence部分。

还有些可靠性是worker自己来保证的,如task执行过程中抛出异常,这种情况是否要重新执行该task,celery的处理如下:

在celery中,task在被worker执行过程中如果抛出异常(Exception),celery会捕获并给Rabbitmq发acknowledgment,如果我们想让该task重新执行,也可以,那就要自己手动捕获异常,

并抛出Retry exception,这样worker会再次执行该task,这个过程中不会与Rabbitmq交互。

1、celery中的基本概念

2、Rabbitmq中的基本概念

publish:即生产者将消息发送给Rabbitmq的过程,更准确的说,是发送给Rabbitmq exchange的过程,在Rabbitmq的控制台网页中的overview子页的Message rates中有publish一项,它指

的是指消息进入Rabbitmq的速率。

3、celery中的配置项

CELERYD_PREFETCH_MULTIPLIER

乘子,worker的进程数*CELERYD_PREFETCH_MULTIPLIER=worker每次从Rabbitmq一次性取走多的消息数

4、Rabbitmq配置项和查询命令

首先几乎所有的控制命令都通过rabbitmqctl执行,很多东西在网页管理页可以看到

rabbitmqctl list_queues

查看queue相关的信息,后面可加参数name(名称),messages(消息数量), consumers(消息者数量,该值与worker数不相等,一般是worker数的三倍,貌似每个worker顺带两个额外的consumer,这两

个consumer我们不用关心)

rabbitmqctl list_exchanges

查看所有exchange,如下,第一列是名称,第二列是exchang type。Rabbitmq共有四种类型:direct,fanout,headers,topic。

direct是指将消息直接发到指定队列,fanout是指广播,发给绑定到该exchange的所有队列。我们一般是用direct。

在celery中,当broker是Rabbitmq时,会调用Rabbitmq创建默认的exchange和默认的queue,它们的名称都是celery,并且该queue是没有绑定任何exchange的,给Rabbitmq发消息时会指定队列,exchange

将消息发到该指定的队列。貌似基本上不会用到绑定功能

C:\Work\hera\src>rabbitmqctl list_exchanges
Listing exchanges ...
        direct
amq.direct      direct
amq.fanout      fanout
amq.headers     headers
amq.match       headers
amq.rabbitmq.log        topic
amq.rabbitmq.trace      topic
amq.topic       topic
celery  direct
celery.pidbox   fanout
celeryev        topic
reply.celery.pidbox     direct
...done.

C:\Work\hera\src>

service rabbitmq-server start

启动rabbitmq

Celery和Rabbitmq自学的更多相关文章

  1. Flask、Celery、RabbitMQ学习计划

    Flask (9.16-9.23) 相关组件了解 (9.16-17) WSGI:Werkzeug 数据库:SQLAlchemy   *重点查看 urls和视图 (9.18-19) session和co ...

  2. How Instagram Feeds Work: Celery and RabbitMQ(转)

    原文:http://blogs.vmware.com/vfabric/2013/04/how-instagram-feeds-work-celery-and-rabbitmq.html Instagr ...

  3. celery使用rabbitmq报错[Errno 104] Connection reset by peer.

    写好celery任务文件,使用celery -A app worker --loglevel=info启动时,报告如下错误: [2019-01-29 01:19:26,680: ERROR/MainP ...

  4. 用Python组合Celery Redis RabbitMQ进行分布式数据抓取

    首先,记录下遇到的问题吧,在抓取的过程中为了避免IO操作,主要用Redis做插入缓存,当内存占用率很大时,会周期性的持续到Mysql里 虽然是拆东墙补西墙,但把数据抓取完毕后持续化可以慢慢进行,毕竟数 ...

  5. celery+RabbitMQ 实战记录2—工程化使用

    上篇文章中,已经介绍了celery和RabbitMQ的安装以及基本用法. 本文将从工程的角度介绍如何使用celery. 1.配置和启动RabbitMQ 请参考celery+RabbitMQ实战记录. ...

  6. Airflow 配置celery+rabbitmq和celery+redis

    Airflow 配置celery+rabbitmq 1.安装celery和rabbitmq组件 pip3 install apache-airflow[celery] pip3 install apa ...

  7. airflow 安装配置celery+rabbitmq celery+redis

    AirFlow的安装可以参考:https://www.cnblogs.com/braveym/p/11378851.html 这里介绍的是AirFlow 安装配置celery+rabbitmq   和 ...

  8. 【Python】分布式任务队列Celery使用参考资料

    Python-Celery Homepage | Celery: Distributed Task Queue User Guide - Celery 4.0.2 documentation Task ...

  9. python celery 时区&结果(性能)的坑

    本文主要介绍最近使用celery遇到的两个坑.关于时区,以及是否保留结果(celery使用rabbitmq). 先说结论:定时任务记得配置时区:丢弃结果对使用rabbitmq对celery来说,性能提 ...

随机推荐

  1. Centos下查看和修改网卡Mac地址

    linux/Centos下查看网卡Mac地址,输入命令: #ifconfig -a eth0 Link encap:Ethernet HWaddr 00:e4:56:2E:D8:20 00:e4:56 ...

  2. js 动态设置 option 的selected 选项

    思路:通过for循环判断每个选项,一旦满足条件则设置其selected属性为true即可,关键代码: var obj = document.getElementById(select_id); for ...

  3. Ubuntu 13.04 安装 Oracle11gR2

    #step 1: groupadd -g 2000 dbauseradd -g 2000 -m -s /bin/bash -u 2000 griduseradd -g 2000 -m -s /bin/ ...

  4. 如何用ChemDraw建立多中心结构

    通过调整ChemDraw多中心机构的连接可绘制有意义的络合物结构,建立中心原子和络合配体后,利用多中心化学键连接上述结构即可.以下内容将具体介绍如何用ChemDraw建立多中心结构. 一.多中心键和多 ...

  5. Asp.net 程序优化js,css合并与压缩

    访问时将js和css压缩并且缓存在客户端,采用的是Yahoo.Yui.Compressor组件还完成的,从这里可下载 创建一个IHttpHandler来处理文件 ) }; )              ...

  6. X-code 描述文件的位置

    不管是真机测试还是打包的过程中,都需要描述文件.在桌面上,按快捷键“commd+Shift+G”,就会显示一个要填的文件路径,如下图: 找到描述文件的路径: ~/Library/MobileDevic ...

  7. Cesium - 离线使用方法

    使用Cesium可以直观的看基于DEM切片产生的Terrain地形数据,有种身临其境的感觉,但缺点是Cesium默认缺省加载了微软Bing提供的地形以及遥感影像数据,可以跟踪日志,总提示让你申请微软的 ...

  8. PHP之ob_start()控制缓冲生成html

    输出控制函数不对使用 header() 或 setcookie(), 发送的文件头信息产生影响,只对那些类似于 echo() 和 PHP 代码的数据块有作用. 我们先举一个简单的例子,让大家对Outp ...

  9. LNMP redis 安装、PHPredis扩展配置、服务器自启动、redis认证密码

    背景: LNMP 环境(centos7) 一. 安装redis 1.下载,解压,编译 $ cd /usr/local$ wget http://download.redis.io/releases/r ...

  10. POJ 3122 Pie

    题目大意: 给出n个pie的直径,有f+1个人,如果给每人分的大小相同(形状可以不同),每个人可以分多少.要求是分出来的每一份必须出自同一个pie,也就是说当pie大小为3,2,1,只能分出两个大小为 ...