前言:python
有朋友問我,我那個任務隊列是怎麼實現,他的疑問其實主要是celery不支持多線程。先說說我那實現的方法,其實個人作法和celery、rq這樣的框架很像的,都是把任務push到隊列裏面,而後pull取出任務而已,celery裏面還能夠取任務,我這個是經過傳送uuid來實現的。 朋友問celery不支持多線程,那是他沒有好好看文檔。celery是支持多任務併發的,哎。。。 好好看文檔呀。mongodb
原文:http://rfyiamcool.blog.51cto.com/1030776/1530826 後端
隊列存儲brokers用的是rabbitmq,後面測試下用mongodb搞搞。我這裏作個測試:bash
下面是tasks.py文件,也就是celery能支持異步的函數。多線程
@app.task def add(x, y): wlog() sleep(10) return x + y
後端啓動含有100個線程的線程池。併發
celery -A tasks worker -c 100 --loglevel=info
在ipython測試的結果:app
看看我本身輸出的日誌,結果很明顯,是併發的:框架
原文:http://rfyiamcool.blog.51cto.com/1030776/1530826 異步
celery是支持好幾個併發模式的,有prefork,threading,協程(gevent,eventlet)ide
prefork在celery的介紹是,用了multiprocess來實現的。多線程就補多少了,估計你們都懂。
說說協程,進程 線程常常玩,也算熟悉,話說協程算是一種輕量級進程,但又不能叫進程,由於操做系統並不知道它的存在。什麼意思呢,就是說,協程像是一種在程序級別來模擬系統級別的進程,因爲是單進程,而且少了上下文切換,因而相對來講系統消耗不多,並且網上的各類測試也代表,協程確實擁有驚人的速度。而且在實現過程當中,協程能夠用之前同步思路的寫法,而運行起來確是異步的,也確實頗有意思。話說有一種說法就是說進化歷程是多進程->多線程->異步->協程,固然協程也有弊端,可是若是你的任務類型不是那種cpu密集的,那選用協程是個好選擇。
可是須要說明的是,雖然celery官網提示說,只要在啓動worker的時候,指明下類型就好了,可是若是你邏輯裏面的模塊有些不支持協程 gevent或者是eventlet異步的話,他仍是會堵塞的。
gevent1.x以後雖然是支持subprocess的用法,gevent這個模塊給非堵塞了,和他有一樣功能的os.popen('sleep 10').read() 是會堵塞的,聽說gevent官方不支持popen的協程的用法。
看了下celery 針對gevent方面的調用,他其實就是引入了gevent的patch 。 那這樣會形成堵塞的問題,若是gevent不支持這些模塊,那。。。。
from gevent import monkey monkey.patch_all()
反之threading的用法卻是簡單明瞭,支持把任務放在線程pool裏面來處理。
話說回來,個人title爲何說gevent來提升性能。我和小夥伴作一些gevent支持的模塊寫函數,作多任務處理的時候,性能確實要比threading要高,還要穩定。
小計:
清理celery產生的數據
#清空 celery purge #清空 from celery.task.control import discard_all discard_all()
查看celery rabbitmq隊列信息
rabbitmqctl list_queues
沒了 !