• django-celery定时任务以及异步任务and服务器部署并且运行全部过程


    Celery

    应用Celery之前,我想大家都已经了解了,什么是Celery,Celery可以做什么,等等一些关于Celery的问题,在这里我就不一一解释了。

    应用之前,要确保环境中添加了Celery包。

    pip install celery
    pip install dajngo-celery

    安装完成之后我们还需要安装,Redis or RabbitMQ 需要用到它们来建立消息队列来完成收,发任务。

    RabbitMQ用户手册:

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

    Redis中文官网:

    http://www.redis.cn/

    用以上两种作为消息处理队列都可以,今天我们来使用Redis来作为队列。

    本人是用Windows来测试,后边有Linux安装方法。

    下载安装包链接: https://github.com/MSOpenTech/redis

    打开链接之后,出现如下页面,然后点击     releases

    进入到下载页面之后,找到需要下载的版本,测试版本(3.0.500)然后点击版本名称进入当前版本页面。

    下载之前需要注意的是,红框中,第一个msi后缀的是微软格式的安装包,第二个zip是压缩包。

    下载完成之后,双击msi文件。

    安装完成之后,以便从程序后续能够正常工作,添加访问密码,

    打开安装目录,找到  redis.windows-service.conf 配置文件,用文本编辑器打开,找到 requirepass字样的地方,添加一行 requirepass 密码。 这是访问redis时需要的密码。一般情况下是可以不用设置的,但是建议还是设置一下。(我用Notepad++打开的)位置:386 

    配置完成之后,点击"开始>右击"计算机">"管理", 在左侧找到"计算机管理(本地)">服务和应用程序>服务,再在右侧找到Redis名称的服务,查看启动状态,没有启动则手动启动,一般情况下服务该正常运行了。

    Redis服务启动过程中,报位置错误的情况下,解决办法如下:

    1、打开redis安装目录找到redis.windows.conf文件拉到底部,添加  maxmemory 209715200

    2、添加完成之后保存退出,打开终端,用命令启动, redis-service.exe redis-windows.conf

    3、启动过程中在报错,错误信息: 

    [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("
    ")
    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
    ")
        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守护进程以及配置全部完成,    以上由本人全部亲测,一步一步写进博客,如有问题,请及时提出。见到第一时间修改。/抱拳

  • 相关阅读:
    SAP的一些HR函数
    如何在sap的screen中使用ListBox
    关于SAP的SD的定价公式的资料(强力推荐,有时间我会进行翻译)
    如何设计和使用自定义的权限对象(自定义权限检查函数)
    [转载]ASP.NET面试题收集
    [转载]sql in与exists区别
    删除A数据表中的一行数据时,不小心将表名写成了B,现在想恢复B中刚删除的的着一行数据怎么办
    删除A数据表中的一行数据时,不小心将表名写成了B,现在想恢复B中刚删除的的着一行数据怎么办
    oracle优化总结经验
    oracle优化总结经验
  • 原文地址:https://www.cnblogs.com/wuyongcong/p/9773345.html
Copyright © 2020-2023  润新知