tornado+celery+flower+supervisor部署的簡化操作

【更改於2016-12-07】

強烈不建議把開celery的命令放到自己項目的main.py中通過開進程的方式去做。

因爲會報一個錯誤:missed heartbeat

找了google, stack-overflow, segmentfault 。。。 很多人提問,然而並沒有解決方案。

我把這些celery放到supervisor中,不再用程序開進程的方式去開,竟然解決了這個問題。

但,我不知道爲什麼。和同事討論了,發現可能是程序開進程可能和命令行手打不一樣。

下一篇可能會研究下python的subprocess和手動的有何不一樣。

=======================================================


背景:

最近在重構,加入RabbitMQ,在本地開發沒覺得麻煩,然而部署到測試機上,發現要敲如下命令:

celery -A task worker -l info -c 5  # 開啓rabbitmq,-l 是--loglevel的縮寫,日誌level,-c 是--concurrency 的縮寫,worker併發數
celery -A task flower               # 用flower監視celery 
supervisorctl> restart myapp        # 重啓myapp
tail -n 50 -f myapp.log             # 查看日誌


解決方案:

好尷尬,所以就在tornado的入口main.py中這麼配置:

# 開輔助子進程
if SETTINGS.api_status == 1: # 正式機
    cmd_list = [
        '/home/www/myApp/venv/bin/python /home/www/myApp/venv/bin/celery -A task worker -c 10',
        '/home/www/myApp/venv/bin/python /home/www/myApp/venv/bin/celery -A task flower',
    ]
elif SETTINGS.api_status == 2: # 測試機
    cmd_list = [
        '/home/www/myApp/myapp_env/bin/python /home/www/myApp/myapp_env/bin/celery -A task worker -c 5',
        '/home/www/myApp/myapp_env/bin/python /home/www/myApp/myapp_env/bin/celery -A task flower',
    ]
elif SETTINGS.api_status == 3: # 開發機
    cmd_list = [
        'celery -A task worker -c 1',
        'celery -A task flower',
    ]


import subprocess
p_list = []
for cmd in cmd_list:
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    logging.info(u"外部命令:%s, 進程id=%s" % (cmd, p.pid))
    p_list.append(p)
    
# 開啓 ioloop循環
tornado.ioloop.IOLoop.instance().start()
logging.info('Exit Master')


# 殺死之前的輔助子進程
for p in p_list:
    logging.info(u'殺死之前的輔助子進程,pid=%s' % p.pid)
    p.kill()
意思很簡單,就是在tornado跑起來之前,先把celery跑起來。

主要是subprocess,當不指定參數env的時候,子進程是用父進程的環境,這就很好,不用去補全那環境的路徑,而且不用硬編碼

然鵝,報錯找不到celery,python的路徑,是因爲在服務器是用supervisor+uwsgi去控制,它開的子進程沒法找到tornado父進程所在的環境。只能老老實實硬編碼去補全了python和celery路徑。

此處部署的第一個坑。


本來以爲到此爲止了,然鵝,子進程們並沒有被殺掉。

查看了下supervisor文檔,發現一個參數:killasgroup=false,當爲true時,殺死子進程們。

修改配置:vi /etc/supervisor.conf

[program:myapp]
command=/home/www/myApp/myapp_env/bin/python main.py --port=9999
directory=/home/www/myApp
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
stdout_logfile=/home/www/myApp/log/supervisor.log
stderr_logfile=/home/www/myApp/log/supervisor.err
killasgroup=true

supervisorctl>  reload 下。

此處部署的第二個坑。

至此,就能單純用supervisor去控制項目開關啦,簡化了部署操作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章