异步消息队列,也能用于定时和周期性任务。每次修改的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. js 补零方法,如果不足位数

    var pad = function() { var tbl = []; return function(num, n) { var len = n-num.toString().length; if ...

  2. js计算两个时间相差天数

     //两个时间相差天数 兼容firefox chrome    function datedifference(sDate1, sDate2) {    //sDate1和sDate2是2006-12 ...

  3. PHP利用memcache缓存技术提高响应速度

    PHP下memcache模块是一个高效的守护进程,提供用于内存缓存的过程式程序和面向对象的方便的接口,特别是对于设计动态web程序时减少对数据库的访问.memcache也提供用于通信对话(sessio ...

  4. 利用GetType反射方法再调用方法进行传递参数实现调用

    直接上代码: TestMenuService.MenuServiceCSClient tesClient = new TestMenuService.MenuServiceCSClient(); va ...

  5. mybatis由浅入深day02_9.3.5使用生成的代码_9.4逆向工程注意事项

    9.3.5 使用生成的代码 需要将生成工程中所生成的代码拷贝到自己的工程中. 拷这4个到我们原来的spring_mybatis1216工程下 ItemsMapper.java package cn.i ...

  6. python文件和目录操作方法大全(含实例)【python】

    转自:http://www.jb51.net/article/48001.htm 一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Py ...

  7. MySQL只有information_schema,test两个数据库

    一.现象 1.今天登上数据库,用 mysql -uroot -proot 登录(本人密码是root),出现: 2.然后尝试 无密码登录,竟然登录成功: 3.查看mysql中的数据库,发现只有两个系统表 ...

  8. weblogic11g重置控制密码

    Reset the AdminServer Password in WebLogic 11g and 12c If you forget the AdminServer password for yo ...

  9. VR室内定位系统小结

    一.写在开始之前 不管是HTC 的Vive还是OC的CV1,都说明VR 定位设备和手柄都会成为未来VR的发展趋势. VR目前关键就是体验,全身心的投入,身临其境的感觉. 不能总玩着玩着,出戏了.这肯定 ...

  10. SpringMVC配置session过期拦截器,返回登录页面

    spring-mvc.xml配置 <mvc:interceptors> <!-- session失效拦截器 --> <mvc:interceptor> <!- ...