python celery非同步任務隊列(redis + supervisor)例子

來源:互聯網
上載者:User

celery簡介:
celery是一個非同步任務隊列/基於分布式訊息傳遞的作業隊列。它側重於即時操作,但對調度支援也很好。 celery是用Python編寫的,但該協議可以在任何語言實現。更多簡介的請自己在網上搜尋
 
本文目的是用python使用celery做非同步任務,在centos 6.4上安裝celery,並用supervisor來管理celery進程,celery採用redis做中介軟體的訊息傳輸。現實中可以celery做非同步請求,如發送郵箱,發送訊息,請求URL等情境
 
環境部署
 
環境
系統:centos 6.4 64位
python版本:2.6.6
 
建立相關的目錄
mkdir -p /data/{redis,logs,www}
(我會把python指令碼都放在/data/www中)
 
安裝celery
yum install python-devel python-setuptools
easy_install pip
pip install celery
pip install redis   #(python中的redis模組)
 
安裝 supervisor
pip install supervisor
echo_supervisord_conf > /etc/supervisord.conf
如果在執行echo_supervisord_conf > /etc/supervisord.conf時報pkg_resources.DistributionNotFound: meld3>=0.6.5錯誤的話,找到supervisor-3.1.3-py2.6.egg-info/requires.txt,把檔案裡面meld3 >= 0.6.5注釋掉,然後再執行echo_supervisord_conf > /etc/supervisord.conf就好了
 
尋找方法:
find / | grep requires.txt
 
配置
vim /etc/supervisord.conf
 
在配置後面添加以下參數
[program:celery]
command=/usr/bin/celery worker -A tasks
directory=/data/www
stdout_logfile=/data/logs/celery.log
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=QUIT
注釋
;program:celery 要管理的進程名,你自己隨便定義,我這定義了叫celery
;command  是啟動celery的命令
;directory  是程式目錄 ,因為我要啟動celery,需要進入/data/www目錄中才會生效的,所以這裡在啟動命令時,會切換到這個目錄裡
;autorstart  自動重啟celery
;stdout_logfile  存放celery的日誌路徑
 
以上命令的大概意思就是:
進行到/data/www目錄,然後執行/usr/bin/celery worker -A tasks,並把輸出的日誌儲存到/data/logs/celery.log中,這是指定了worker模式,如果不指定,預設為prefork模式,一般你機器有幾核,系統就開啟幾個worker進程,如果有異常,記得查看日誌/data/logs/celery.log
 
安裝redis
cd /usr/local/src
wget http://download.redis.io/releases/redis-3.0.5.tar.gz
tar xf redis-3.0.5.tar.gz
cd redis-3.0.5
make
make install
#(可用make PREFIX=/usr/local/redis install 安裝到指定的路徑下面 ) 
cp utils/redis_init_script /etc/init.d/redis
chmod a+x /etc/init.d/redis
mkdir /etc/redis
cp redis.conf /etc/redis/
 
簡單修改redis.conf(前面數字是行號)
42 daemonize yes                                                  #進程轉入後台運行
50 port 22222                                                        #修改連接埠,不用預設的6379
69 bind 127.0.0.1                                                   #綁定IP,只能本地串連
192 dir /data/redis                                                #修改redis檔案存放路徑
396 requirepass DILSi3_dflka_f3i_LFKDkdf!idf      #設定密碼
453 maxmemory 256M                                       #redis最大使用256M記憶體,我的是虛擬機器,所以記憶體設定小
注釋:
requirepass DILSi3_dflka_f3i_LFKDkdf!idf  是配置redis密碼,用戶端串連和關閉redis時需要此密碼
 
修改/etc/init.d/redis(前面數字是行號)
6 REDISPORT=22222
7 EXEC=/usr/local/bin/redis-server
8 CLIEXEC=/usr/local/bin/redis-cli
9 PASSWD="DILSi3_dflka_f3i_LFKDkdf!idf"        #增加行
10 PIDFILE=/var/run/redis.pid
11 CONF="/etc/redis/redis.conf"
30                 $CLIEXEC -p $REDISPORT -a $PASSWD  shutdown
注釋:
關閉redis時,需要帶上redis密碼,否則失敗,如果沒有設定密碼,則不需要帶密碼關閉
 
啟動redis
service redis start
 
查看redis進程
ps -ef |grep redis
root     28631     1  0 04:30 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:22222
root     28635  1542  0 04:31 pts/0    00:00:00 grep redis
 
編寫celery指令碼、
cd /data/www
vim tasks.py
#!/usr/bin/env python
#coding:utf-8
import time
#匯入celery相關模組、方法
from celery import Celery
from celery import platforms
#因為supervisord預設是用root啟動並執行,必須設定以下參數為True才能允許celery用root運行
platforms.C_FORCE_ROOT = True
#配置celery,串連redis,DILSi3_dflka_f3i_LFKDkdf!idf是redis的密碼,22222是連接埠 10是庫(redis有16個庫,這取第11個,即10)
config={}
config['CELERY_BROKER_URL'] = 'redis://:DILSi3_dflka_f3i_LFKDkdf!idf@127.0.0.1:22222/10'
config['CELERY_RESULT_BACKEND'] = 'redis://:DILSi3_dflka_f3i_LFKDkdf!idf@127.0.0.1:22222/10'
#不需要返回任務狀態,即設定以下參數為True
config['CELERY_IGNORE_RESULT'] = True
app = Celery("tasks", broker=config['CELERY_BROKER_URL'])
app.conf.update(config)
@app.task
def output(num):
"""輸出傳進來的數字,在輸出前等待2秒"""
    time.sleep(2)
    print num
 
啟動supervisord
/usr/bin/supervisord
 
查看是否啟動成功
[root@drfdai www]# ps -ef |grep supervisor
root     28656     1  0 04:52 ?        00:00:00 /usr/bin/python /usr/bin/supervisord
root     28692  1542  0 04:53 pts/0    00:00:00 grep supervisor
 
啟動celery:
supervisorctl start celery
 
查看celery是否串連成功redis
tailf /data/logs/celery.log
能看到[2015-11-16 05:05:27,938: WARNING/MainProcess] celery@drfdai ready.說明串連成功
 
測試
在終端【終端1】中開啟即時日誌:
[root@drfdai www]# tailf /data/logs/celery.log
 
開啟另一終端【終端2】測試:
[root@drfdai ~]# cd /data/www
[root@drfdai www]# python
Python 2.6.6 (r266:84292, Jul 23 2015, 15:22:56)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from tasks import output
>>> for i in xrange(20):
...     output.apply_async(args=[i])
...
<AsyncResult: 38a14673-3ce6-4244-b262-d488aa637ff9>
<AsyncResult: 3ff1b2c0-4b37-4c70-a543-d7c58111cb99>
<AsyncResult: 355c232f-c419-43d5-bf8f-afa4d7084136>
<AsyncResult: c3089d05-d430-4fd4-bfba-112d6dd5b635>
<AsyncResult: 842db1ad-5490-456d-82d8-e81e60db244b>
<AsyncResult: fe0dd54a-8bad-43e2-a8b8-b87be158cf16>
<AsyncResult: edd95275-a3b3-46a5-8e21-b88c7faedbe9>
<AsyncResult: c21b9c62-644d-4171-bb68-9a371af60283>
<AsyncResult: 29d38896-9d4d-4b97-8e27-6a7209f06dc9>
<AsyncResult: 7c3ba209-01fd-44d3-9645-f9c85d799eaf>
<AsyncResult: b08bbb7a-341b-436c-8ef4-be954b1fcbc5>
<AsyncResult: b03193a2-c6d6-49ff-ac27-b453593050c4>
<AsyncResult: 1be6394c-09c3-4f48-9ed4-1114fd1af637>
<AsyncResult: b496cdd3-3032-41ad-939e-414198c9056a>
<AsyncResult: 0dd365ea-383b-4c93-9ed0-406bcff6f41b>
<AsyncResult: ce60892e-d640-4589-8a8b-3a7f18e8c6d3>
<AsyncResult: df4fd3c4-d9e8-474b-b60f-c6e11283564a>
<AsyncResult: 83e7d36c-fc42-4f3b-8941-df40fa13a517>
<AsyncResult: 9b25f7f7-c3bc-4bb0-8a1f-27ceec59cf0c>
<AsyncResult: f0d7e201-032b-41a0-8e7a-c02681c31947>
 
切換到【終端1】可以看到,每隔2秒就會列印一行日誌
warnings.warn(CDeprecationWarning(W_PICKLE_DEPRECATED))
[2015-11-16 05:58:09,687: WARNING/MainProcess] celery@drfdai ready.
[2015-11-16 05:59:18,816: WARNING/Worker-1] 0
[2015-11-16 05:59:19,826: WARNING/Worker-1] 1
[2015-11-16 05:59:20,830: WARNING/Worker-1] 2
[2015-11-16 05:59:21,836: WARNING/Worker-1] 3
[2015-11-16 05:59:22,841: WARNING/Worker-1] 4
[2015-11-16 05:59:23,848: WARNING/Worker-1] 5
[2015-11-16 05:59:24,853: WARNING/Worker-1] 6
[2015-11-16 05:59:25,858: WARNING/Worker-1] 7
[2015-11-16 05:59:26,864: WARNING/Worker-1] 8
[2015-11-16 05:59:27,873: WARNING/Worker-1] 9
[2015-11-16 05:59:28,884: WARNING/Worker-1] 10
[2015-11-16 05:59:29,892: WARNING/Worker-1] 11
[2015-11-16 05:59:30,899: WARNING/Worker-1] 12
[2015-11-16 05:59:31,908: WARNING/Worker-1] 13
[2015-11-16 05:59:32,912: WARNING/Worker-1] 14
[2015-11-16 05:59:33,920: WARNING/Worker-1] 15
[2015-11-16 05:59:34,926: WARNING/Worker-1] 16
[2015-11-16 05:59:35,933: WARNING/Worker-1] 17
[2015-11-16 05:59:36,939: WARNING/Worker-1] 18
[2015-11-16 05:59:37,944: WARNING/Worker-1] 19
 
當我們在【終端2】中調用此函數後,執行並沒有受到time.sleep(2)的影響,執行後馬上就結束了,而【終端1】每隔2秒就輸出1行日誌,這日誌是函數output輸出來的。
 
實用代碼片斷:
vim common/tasks.py
#匯入發送郵件模組
from email.mime.text import MIMEText
import smtplib
import json
import datetime
from celery import Celery
from celery import platforms
import requests
#匯入設定檔
from config import setting
#發送郵箱配置
smtp = setting.smtp
user = setting.user
passwd = setting.passwd
此處省略……
@celery.task
def sendMail(mail):
    '''
    to_list 接收者郵件,每個郵件地址用","分隔,str格式
    subuect 郵件主題,str格式
    context 郵件內容,str格式
    '''
    to_list = mail.get('to_list')
    subject = mail.get('subject')
    context = mail.get('context')
    msg = MIMEText(context,'html','utf-8')
    msg['Subject'] = subject
    msg['From'] = "linux系統營運<%s>" % user
    to_list = list(to_list.split(','))
    msg['To'] = ",".join((to_list))
    try:
        s = smtplib.SMTP()
        s.connect(smtp)
        s.login(user,passwd)
        s.sendmail(user,to_list,msg.as_string())
        s.close()
        return json.dumps({"redid":0,"redmsg":"發送成功"})
    except Exception,e:
        print 'Error: %s' % e
        return json.dumps({"redid":-1,"redmsg":"發送失敗"})
 
在實際項目中調用此方法,做非同步郵箱發送,發送後不需要等待返回的結果
#/usr/bin/env python
#coding:utf-8
from common.tasks import sendMail
sendMail.delay(dict=(to_list ='xxxxxxxx@qq.com',subject ='郵件發送測試',context ='<h1>郵件收到</h1><br />測試沒問題'))

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.