Celery学习记录

用到的python包:celery--3.1.25;django--1.11.26;python2.7.15;reids--2.10.6;

redis:4.0.11 (后来换的)

一、celery文档

首先,附上官方文档连接https://docs.celeryproject.org/en/latest/

celery3.1.7文档:http://docs.jinkan.org/docs/celery/index.html

二、安装及调试(centos7环境)

由于centos7中不直接支持ifconfig命令,因此,先解决了ifconfig及yum命令支持。此处,我是通过使用Xshell进行的远程访问,习惯用ifconfig进行查看ip建立连接。Xshell下载地址,支持个人用户免费使用。

1、Xshell的使用简单说明

安装后点击“文件”--“新建”,即可见下方窗口

在用户身份认证中,填写用户名密码

在左侧生成的图标处进行双击,以打开会话界面。支持打开多个。

2、安装redis作为后续celery的broker使用

下载及解压安装(下载安装的地址建议自行创建一个文件夹)

wget http://download.redis.io/releases/redis-5.0.5.tar.gz     (具体版本根据情况自行选择)

tar -zxvf redis-5.0.5.tar.gz    (如果要解压到指定位置,后跟 "-C 目标位置",例如:"-C /usr/local")

cd redis-5.0.5    (如果解压缩到了指定位置,先调转到解压的位置后,执行此命令)

make

make过程中遇到了错误及解决办法(参考:CentOS7中编译安装redis5.0

此处问题解决是参考了上述文章,跳转到deps目录中,执行 make hiredis lua jemalloc linenoise 命令。

make成功后显示:

配置文件修改:

1、注释掉bind 127.0.0.1,以开发给其他计算机使用

2、关闭保护模式

启动redis(假设redis解压到了usr/local/ 目录下):

/usr/local/redis-5.0.5/src/redis-server    /usr/local/redis-5.0.5/redis.conf(服务端启动)

/usr/local/redis-5.0.5/src/redis-cli   (客服端)(新的交互窗口开启)

服务端启动成功会出现如下画面:

注:关闭Redis服务命令:src/resdis-cli shutdown 

3、安装支持的Python包

pip install redis

pip install -U "celery[redis]"    #  pip install "celery[librabbitmq,redis,auth,msgpack]"

4、新建一个文件夹,创建一个tasks.py文件,作为celery application定义任务列表

# -*- coding:utf-8 -*-

from celery import Celery

# 使用redis作为broker及backend
app = Celery('tasks',                               # 名字
             broker='redis://127.0.0.1:6379/1',     # broker
             backend='redis://127.0.0.1:6379/2')    # backend存储结果


# 创建任务函数
@app.task
def add(x, y):
    print("running...")
    return x + y

保存文件。

注:这里Celery的第一个参数“名字”,需要确保其与celery发布任务的“名称前缀(最后一个点前的部分)”保持一致,否则会报错“celery.exceptions.NotRegistered”。

5、启动一个celery worker开始监听,并等待执行任务

celery -A tasks worker -l info    (在tasks.py目录中执行此命令)

另外,windows环境中,上述语句后还需要参数“-P eventlet”(如果有模拟浏览器的task,一定不要加,血的教训)

遇到问题(没有记录是啥问题),解决是通过安装了一个Python的包 pip install 'more-intertools<=5.0.0'

成功的界面:

6、调用任务

打开新的终端页面,cd到tasks.py所在的目录,进入Python交互界面。调用tasks.py中的add函数,通过delay()apply_async()函数,将任务发布到broker。

在 worker 监听终端(执行过 celery -A tasks worker --loglevel=info 的终端页面),可以看到worker收到并执行了任务。

 三、在项目中使用celery

同样的需要启动Redis作为broker,方法同上,这里不再赘述。

创建项目,这里我使用的是在windows环境中,使用pycharm进行创建项目,同步到远程服务器中的方法。pycharm同步服务器代码的方法参考:Pycharm连接远程服务器实现代码同步

项目结构如下图:

这里创建的项目名为celeryProject1,包含文件:“__init__.py,celery.py(app), config.py(配置文件),tasks.py(任务)”。

1、celery.py

# -*- coding:utf-8 -*-

from __future__ import absolute_import, unicode_literals
from celery import Celery

# 创建celery实例
app = Celery('demo')
# 导入配置文件
app.config_from_object('celeryProject1.config')
# 自动发现task
app.autodiscover_tasks(['celeryProject1'])

2、config.py  (官方文档

# -*- coding:utf-8 -*-
"""参数配置见官方文档说明:http://docs.celeryproject.org/en/latest/userguide/configuration.html#configuration"""
# from kombu import Exchange, Queue

BROKER_URL = 'redis://127.0.0.1:6379/3'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/4'
CELERY_IMPORTS = ('celeryProject1.tasks1',)

3、task1.py

# -*- coding:utf-8 -*-

from celeryProject1.celery import app


# 创建任务
@app.task
def celery_task1():
    print "this is celery task1..."


@app.task
def celery_task2(x, y):
    print "this is celery task2..."
    return x+y


@app.task
def celery_task3(x, y):
    print "this is celery task3..."
    return x*y

项目文件完成之后,同步到服务器中。

使用Xshell工具,打开服务器交互界面,cd到项目所在的文件夹。执行:

 celery -A celeryProject1 worker -l info

 开启celery任务。

打开新的Xshell交互窗口,cd到项目所在目录,开启Python环境:

发布任务:

此时,我们可以在celery服务监控界面,看到任务的执行情况:

由上可见,celery项目必要的内容包括:app、配置文件、任务。

需要开启的窗口界面:Redis(作为broker及backend)、启动worker的监听界面(celery -A XXX worker -l info)、Python发布任务的界面。

四、在Django中使用Celery(Windows)

因为项目本身的缘故,这里将Django环境搭到了windows环境中。Django环境的创建:Django创建项目记录

本部分同时参考了博文:Django中使用CeleryDjango+redis+celery 实现异步任务

创建好Django及app后,现在默认你已经启动了Django服务,后续修改中不需要重启Django,它会自动识别修改过的部分。

1、接下来,修改/添加必要的文件

修改Django的settings文件添加(这里我是用的redis作为了broker及backend,配置的ip地址,此处与实际对应):

# ------------------------------------------------------------------------------------
CELERY_BROKER_URL = 'redis://192.168.236.129:6379/1'  # Broker配置,使用Redis作为消息中间件

CELERY_RESULT_BACKEND = 'redis://192.168.236.129:6379/2'  # BACKEND配置,这里使用redis

CELERY_RESULT_SERIALIZER = 'json'  # 结果序列化方案
# ------------------------------------------------------------------------------------

在与项目的同名python package中添加celery.py文件:

from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名称.settings')  # 设置django环境

app = Celery('项目名称')

app.config_from_object('django.conf:settings') 

# 发现任务文件每个app下的tasks.py
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

修改__init__.py文件(根据此部分参考的博文):

from __future__ import absolute_import
from .celery import app

__all__ = ['app']

在你的app的python package包中添加tasks.py文件(一个实例,根据你的实际需要定义tasks的内容):

# -*- coding: utf-8 -*-

from DjangoCeleryForCrawler.celery import app


@app.task
def celery_task1():
    print "task1 test!"
    # return 111

现在,我的项目目录结构如下(为了不造成不必要的干扰,将非必须文件打码了):

2、开启Celery服务 

好了,我们现在在pycharm点击下边框处的“terminal”打开一个新的交换窗口,执行

celery -A 你的项目名 worker -l debug 

 

可以观察到成功开启了Celery服务。 

打开新的Terminal窗口,执行我们定义的tasks中的任务进行测试:

可以看到监视窗口收到并执行了task:

3、通过分配路由,在浏览器页面调用任务

同此部分“1”,在tasks.py中添加一个task:

@app.task
def test_task1(a, b):
    print "task1 test!"
    return a+b

在同级目录下的views.py中, 调用此task:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import json
import tasks
from django.http import HttpResponse


def test_celery(request, *args, **kwargs):
    sums = tasks.test_task1.delay(1, 2)
    result = {'code': 0, 'msg': str(sums)}
    return HttpResponse(json.dumps(result, ensure_ascii=False), content_type='application/json')

接下来,在项目的urls.py中定义路由:

 在浏览器地址栏输入此地址进行访问:http://127.0.0.1:8000/test_celery/.

 

写在后面:

开始在windows上启动服务时,加了个 -P eventlet 的参数(不知道在哪个教程看到的)。其他task都没问题,有一个task包括启动Chrome浏览器的代码,就有了如下报错:

[2019-11-27 11:03:47,292: ERROR/MainProcess] Task proj.tasks.chrome_test[03e31b41-42b4-46ae-96cc-b856a7f7ae00] raised unexpected: WebD
riverException()
Traceback (most recent call last):
  File "d:\software\professional\python27\lib\site-packages\celery\app\trace.py", line 240, in trace_task
    R = retval = fun(*args, **kwargs)
  File "d:\software\professional\python27\lib\site-packages\celery\app\trace.py", line 438, in __protected_call__
    return self.run(*args, **kwargs)
  File "E:\MyProjects\PythonProject\CeleryChromeTest\proj\tasks.py", line 23, in chrome_test
    options=chrome_options)
  File "d:\software\professional\python27\lib\site-packages\selenium\webdriver\chrome\webdriver.py", line 73, in __init__
    self.service.start()
  File "d:\software\professional\python27\lib\site-packages\selenium\webdriver\common\service.py", line 95, in start
    (os.path.basename(self.path), self.start_error_message, str(e)))
WebDriverException: Message: The executable chromedriver.exe needs to be available in the path. Please see https://sites.google.com/a/chromium.org/chromedriver/home
set_nonblocking() on a file object with no setblocking() method (Windows pipes don't support non-blocking I/O)

这个错误找个N天, 始终不得其解。误打误撞,去掉了“-P eventlet”参数,....,问题解决了。看文档的该部分,是该任务有阻塞调用(blocking calls)

 

# celery的一些task参数

1. (time_limit=20)设置任务最大执行时间

达到时间上限若没有执行完,报错“Process 'Worker-x' pid:xxxx exited with 'signal 15 (SIGTERM)'”,并退出任务。

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值