django-celery定時任務以及異步任務and服務器部署而且運行所有過程

Celery

應用Celery以前,我想你們都已經瞭解了,什麼是Celery,Celery能夠作什麼,等等一些關於Celery的問題,在這裏我就不一一解釋了。html

應用以前,要確保環境中添加了Celery包。python

pip install celery
pip install dajngo-celery

安裝完成以後咱們還須要安裝,Redis or RabbitMQ 須要用到它們來創建消息隊列來完成收,發任務。linux

RabbitMQ用戶手冊:git

https://www.rabbitmq.com/manpages.htmlgithub

Redis中文官網:web

http://www.redis.cn/redis

用以上兩種做爲消息處理隊列均可以,今天咱們來使用Redis來做爲隊列。shell

本人是用Windows來測試,後邊有Linux安裝方法。django

下載安裝包連接: https://github.com/MSOpenTech/redisjson

打開連接以後,出現以下頁面,而後點擊     releases

進入到下載頁面以後,找到須要下載的版本,測試版本(3.0.500)而後點擊版本名稱進入當前版本頁面。

下載以前須要注意的是,紅框中,第一個msi後綴的是微軟格式的安裝包,第二個zip是壓縮包。

下載完成以後,雙擊msi文件。

安裝完成以後,以便從程序後續可以正常工做,添加訪問密碼,

打開安裝目錄,找到  redis.windows-service.conf 配置文件,用文本編輯器打開,找到 requirepass字樣的地方,添加一行 requirepass 密碼。 這是訪問redis時須要的密碼。通常狀況下是能夠不用設置的,可是建議仍是設置一下。(我用Notepad++打開的)位置:386 

配置完成以後,點擊"開始>右擊"計算機">"管理", 在左側找到"計算機管理(本地)">服務和應用程序>服務,再在右側找到Redis名稱的服務,查看啓動狀態,沒有啓動則手動啓動,通常狀況下服務該正常運行了。

Redis服務啓動過程當中,報位置錯誤的狀況下,解決辦法以下:

一、打開redis安裝目錄找到redis.windows.conf文件拉到底部,添加  maxmemory 209715200

二、添加完成以後保存退出,打開終端,用命令啓動, redis-service.exe redis-windows.conf

三、啓動過程當中在報錯,錯誤信息: 

[22420] 11 Oct 11:46:23.351 # Server started, Redis version 3.0.500
[22420] 11 Oct 11:46:23.355 # Can't handle RDB format version 7
[22420] 11 Oct 11:46:23.355 # Fatal error loading the DB: Invalid argument. Exiting.

解決辦法:

刪除全部的dump.rdb文件,重啓新啓動, redis-service.exe文件,報錯緣由,多是rdb文件版本太高或者太低所致使問題出現,

啓動成功界面:

redis啓動成功以後就不要關閉,應爲celery是基於redis來收發任務的, 須要用到redis的隊列。

環境到此安裝完成以後,開始寫個簡單的異步任務。

Celery 異步任務

新建立一個Django項目,添加一個應用。

django-admin startproject celery_sq

新建應用

python manage.py startapp app

項目初始化完成以後,打開settings.py文件

必定要將celery導入進去,纔可使用。緊接着導入須要用到的模塊。

from celery.schedules import crontab
from celery.schedules import timedelta
導入

在settings文件拉到底部,添加如下代碼。

import djcelery
djcelery.setup_loader()
BROKER_URL = 'redis://127.0.0.1:6379/'
CELERY_IMPORTS = ('app.tasks')
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
底部添加代碼

以上代碼添加完成以後再同級目錄下建立 celery.py

from __future__ import absolute_import, unicode_literals
# -*- coding: utf-8 -*-
__author__ = 'YongCong Wu'
# @Time    : 2018/10/9 15:52
# @Email   :  : 1922878025@qq.com
import os
from celery import Celery
from django.conf import settings

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'celery_sq.settings')

app = Celery('celery_sq')

# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))
celery.py

在app目錄下添加tasks.py文件, 注意:一個應用下只能添加一個tasks.py 一個py一遍可寫多個任務。

from __future__ import absolute_import
# -*- coding: utf-8 -*-
__author__ = 'YongCong Wu'
# @Time    : 2018/10/9 16:10
# @Email   :  : 1922878025@qq.com
from celery_sq.celery import app


@app.task
def add(x, y):
   return x + y
tasks.py

添加完成以後,在app同級目錄下的views文件裏邊添加函數。

from django.shortcuts import render, HttpResponse

# Create your views here.
from .tasks import add
import json

def add_handler(request):
    x = request.GET.get('x', 1)
    y = request.GET.get('y', 1)
    result = add(int(x), int(y))
    return HttpResponse(json.dumps({'result': result}))
views.py

添加urls.py

# -*- coding: utf-8 -*-
__author__ = 'YongCong Wu'
# @Time    : 2018/10/10 14:46
# @Email   :  : 1922878025@qq.com


from django.conf.urls import include, url
from django.contrib import admin
from app import views

urlpatterns = [
    url(r'^add/', views.add_handler),
]
urls.py

app 中的url添加完成以後須要在celery_sq目錄下的urls.py中添加。

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^home/', include('app.urls')),    # 添加這個
]    
celery_sq/urls.py

添加完成以後就開始測試咱們的項目,現將項目運行起來。

python manage.pu runserver

項目啓動完成以後,從新打開一個終端,進入項目目錄,啓動django celery 服務。

python manage.py celery worker --loglevel=info

見到這個界面,就說明django celery已經啓動成功了,接下來就開始測試咱們的異步任務了。

測試地址端口可自行修改,根據本身端口來設置:    http://127.0.0.1:9000/home/add/?x=5&y=5

Celery定時任務

 如今每家公司,有各類各樣的需求,有的須要定時去查找數據等等,一些定時的功能。接下來,咱們就用Celery來完成一個定時寫入txt文件的一個任務。

app/tasks.py文件添加如下代碼。

from celery import shared_task

@shared_task
def hello_world():
    with open("output.txt", "a") as f:
        f.write("hello world")
        f.write("\n")
tasks.py

在settings.py下添加

CELERYBEAT_SCHEDULE = {  # 定時器策略
    # 定時任務一: 每隔30s運行一次
    u'測試定時器1': {
        "task": "app.tasks.tsend_email",
        # "schedule": crontab(minute='*/2'),  # or 'schedule':   timedelta(seconds=3),
        "schedule": timedelta(seconds=30),
        "args": (),
    },
}
定時

此時tasks.py文件裏邊有一個定時tasks。

參數定義:

days             天
seconds        秒 
microseconds    微秒
milliseconds      毫秒
minutes            分
hours                小時
timedelta參數含義
month_of_year        月份
day_of_month         日期
day_of_week           周
hour                       小時
minute                    分鐘
crontab參數含義

定時任務添加完成以後,啓動celery beat, celery啓動了一個beat進程一直在不斷的判斷是否有任務須要執行。

celery -A celery_sq beat -l info

從新打開終端,輸入以上命令啓動  celery beat, 啓動成功以後看到以下頁面。

任務成功執行以後狀態

  

到此爲止,在windows下,測試異步任務和定時任務已經完成,那麼有個問題,在windows下執行一下celery須要打開這麼多的終端窗口,哪用linux部署項目的時候該怎麼辦呢,接下來,咱們就在linux下部署。咱們用守護進程的方式來完成。

Linux下部署django-celery

Linux默認Python環境是2.7,須要自行下載Pyhton3.5。(安裝過程自行百度)

linux下,咱們通常用守護進程的方式來啓動 Celery ,否則總不能在打開不少窗口一個窗口啓動一個beat等等吧。

在linux下使用supervisor來守護進程。

supervisor官網:

http://supervisord.org

安裝Redis:

wget http://download.redis.io/releases/redis-2.8.3.tar.gz

安裝完成以後須要解壓,編譯。依次按照如下命令執行。

tar xzf  redis-2.8.3.tar.gz

cd redis-2.8.3

make && make install

安裝supervisor

pip install supervisor

supervisor配置

咱們使用echo_supervisord_conf命令來獲得supervisor配置模板,打開終端shell輸入如下命令。

echo_supervisord_conf > supervisord.conf

 

接下來編輯 supervisord.conf文件

vim supervisord.conf

修改include分發ini文件目錄。

配置完成以後建立conf.d目錄

mkdir conf.d

建立完成以後進入目錄,建立ini文件將如下配置寫入文件中。

測試添加ini文件是否讀取。

在任意目錄下建立hello.py文件,添加如下代碼,來進行測試。

import time
import sys
while True:
    print("test data\n")
    sys.stdout.flush()
    time.sleep(1)

添加完成以後保存,用 python 文件名稱 來執行py文件是否出錯。正確結果:

測試完成以後開始爲hello.py添加進程守護。

進入conf.d目錄添加 hello.ini文件。將如下配置寫入文件。

[program:hello]        名字隨意,不要重複
command=python /home/hello.py
stdout_Logfile=/home/celery_log/hello.log
stderr_logfile=/home/celery_log/hello_error.log
    

運行supervisord

supervisord -c /home/supervisor/supervisord.conf

運行hello進程

supervisordctl -c /home/supervisor/supervisord.conf      運行所有

supervisordctl -c /home/supervisor/supervisord.conf start heelo     指定運行

supervisordctl -c /home/supervisor/supervisord.conf stop heelo     指定中止


參數:  start status stop restart         啓動,狀態, 中止, 重啓

以上圖片是啓動成功以後的狀態。

測試完成以後就開始配置Redis。

添加redis.ini文件,將如下內容添加。

[program:redis]
command=/home/redis-4.0.1/src/redis-server
autostart=true
autorestart=true
startsecs=3
stdout_Logfile=/home/celery_Log/redis.log    標準日誌輸出
stderr_logfile=/home/celery_log/redis_error.log     錯誤日誌輸出
        

添加完成以後須要使用如下命令來加載進程。

supervisorctl reload

因爲 supervisor 管理的進程不能設置爲 daemon 模式,故若是 Redis 沒法正常啓動,能夠查看一下 Redis 的配置,並將daemonize選項設置爲 no。

daemonize no

到文件的地步添加以下信息

[program:celery]

  # 啓動命令入口
  command=/var/www/newweb/venv/bin/celery worker -A celery_worker.celery --loglevel=info

  # 命令程序所在目錄
  directory=/var/www/newweb/

  # 運行命令的用戶名
  user=root

  autostart=true

  autorestart=true

  # 日誌地址
  stdout_logfile=/var/log/newymw2.0/supervisor/newymw2.0_celery.log

另外在celery.worker下設置beat定時任務的進程

[program:celery.beat] 
;指定運行目錄 
directory=/home/xxx/webapps/yshblog_app/yshblog
;運行目錄下執行命令
command=celery -A yshblog worker --loglevel info --logfile celery_beat.log
 
;啓動設置 
numprocs=1          ;進程數
autostart=true      ;當supervisor啓動時,程序將會自動啓動 
autorestart=true    ;自動重啓
 
;中止信號
stopsignal=INT

worker和beat都設置好以後就能夠配置redis了。

[program:redis]
;指定運行目錄 
directory=~/webapps/yshblog_app/lib/redis-3.2.8/
;執行命令(redis-server redis配置文件路徑)
command=redis-server redis.conf
 
;啓動設置 
numprocs=1          ;進程數
autostart=true      ;當supervisor啓動時,程序將會自動啓動 
autorestart=true    ;自動重啓
 
;中止信號
stopsignal=INT

啓動supervisord

supervisord -c /home/supervisor/supervisor.conf

查看進程狀態

supervisorctl -c /home/supervisor/supervisor.conf status all

加載supervisord,在新添加進程的狀況下使用加載,新添加一個,加載一次。

supervisorctl -c /home/supervisor/supervisor.conf reload

運行測試celery過程當中若是出現以下錯誤(celery不能用root用戶來啓動),按照如下步驟添加,便可解決

測試命令:

 celery -A celery_sq worker -l info

錯誤信息:

Running a worker with superuser privileges when the
worker accepts messages serialized with pickle is a very bad idea!

If you really want to continue then you have to set the C_FORCE_ROOT
environment variable (but please think about this before you do).

User information: uid=0 euid=0 gid=0 egid=0

解決辦法:

celery.py添加以下代碼

from celery import Celery, platforms

platforms.C_FORCE_ROOT = True

測試成功頁面

 測試成功以後開始測試beat

測試beat命令:

celery -A celery_sq beat -l info

測試成功頁面:

成功以後守護進程就是這個樣子的。

 

[program:redis]
command=/home/redis-4.0.1/src/redis-server
autostart=true
autorestart=true
startsecs=3
stdout_Logfile=/home/celery_log/redis.log
stderr_logfile=/home/celery_log/redis_error.log
redis.ini
[program:celeryworker]
directory=/root/.pyenv/versions/Celery_prj/celery_sq
command=celery -A celery_sq worker -l info 
autostart=true
autorestart=true
stdout_logfile=/home/celery_log/celery_worker.log
stderr_logfile=/home/celery_log/celery_worker_error.log
worker.ini
[program:celerybeat]
directory=/root/.pyenv/versions/Celery_prj/celery_sq
command=celery -A celery_sq beat -l info
autostart=true
autorestart=true
stdout_logfile=/home/celery_log/celery_beat.log
stderr_logfile=/home/celery_log/celery_beat_error.log
beat.ini

到此爲止,windows以及Linux下django-celery守護進程以及配置所有完成,    以上由本人所有親測,一步一步寫進博客,若有問題,請及時提出。見到第一時間修改。/抱拳

相關文章
相關標籤/搜索