例行:如有错误,敬请指正;
目录
一、背景
为了使用django配置一个长时异步任务,参考了很多资料,很多朋友都推荐使用celery,于是配置了celery+redis的组合来实现;过程中踩了一些坑,分享给大家以避免。
此处django仅拿来写后端,没有写前端的页面。主要是因为博主更熟悉python,拿来写一些功能时,如opencv库,gdal库很方便,做数据库连接可以通过架构,也可以直接连接,也很便利。且前后端分离,避免后端代码明文。
环境描述:ubuntu20.04;;django==4.2;celery==5.2.7;redis==4.5.4;gunicorn==20.1.0;python==3.11
二、实现过程
2.1安装配套的系统工具
打开一个终端,运行以下命令:
sudo apt install libpq-dev;
sudo apt install redis-tools -y;
sudo apt install redis-server -y;
sudo apt install python-celery-common -y;
2.2安装pip包
切到项目的虚拟环境中;使用pip安装对应包;
eg:pip install django==4.2
或者把以下存为一个req.txt,然后在同级目录下切到虚拟环境conda activate {your_env},然后pip install -r req.txt
django==4.2
celery==5.2.7
redis==4.5.4
gunicorn==20.1.0
2.3在django项目中配置celery
django项目的setting同级目录创建tasks.py(长时任务的开发文件),celery.py(celery的配置文件);
在manage.py同级目录创建gunicorn.py(gunicorn的配置文件)
2.3.1配置celery.py
注意celery.py中,一定要在app中配置,backend='redis',以及broker='redis://{yourIP}:6379/0'参数,因为celery work会默认连接mq,而不是连接redis;
# /{appname}/celery.py
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'map_target_slice.settings')
app = Celery('map_target_slice',backend='redis',broker='redis://localhost:6379/0')
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
2.3.2配置tasks.py
在tasks中,import logging,然后logger=logging.getLongger('django');
# /{appname}/tasks.py
from celery import shared_task
import logging
import time
logger = logging.getLogger('django')
@shared_task
def do_test(layers,box,appTaskId):
f = open("aync_log.txt",'a+')
f.write(str(time.time())+str(layers)+str(box)+str(appTaskId))
f.write('\n')
logger.info('start write')
time.sleep(8)
f.write(str(time.time()))
logger.info('suc write')
f.write('\n')
在同级别的__init__.py中配置以下
/{appname}/__init__.py
from __future__ import absolute_import, unicode_literals
# # This will make sure the app is always imported when
# # Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ('celery_app',)
2.3.3配置django中的setting.py
此处主要是将celery默认的日志劫持(CELERYD_HIJACK_ROOT_LOGGER)给关了,这样才能在tasks中使用getLogger,获取
到django日志中
# /{appname}/settings.py
# Celery setting
broker_url = 'redis://127.0.0.1:6379/0'
result_backend = 'redis://127.0.0.1:6379/0'
accept_content = ["json"]
task_serializer = "json"
result_serializer = "json"
CELERYD_HIJACK_ROOT_LOGGER = False
LOGGING={
'version':1,
'disable_existing_loggers':False,
'loggers':{
'django':{
'handlers':["file"],
'level':'INFO',
'propagate':True
},
},
'handlers':{
'file':{
'level':'INFO',
'class':'logging.FileHandler',
'filename':{YOUR_LOG_FILE_PATH},
'formatter':'default',
},
},
'formatters':{
'default':{
'format':'%(asctime)s %(levelname)s %(filename)s:%(lineno)d %(message)s'
}
}
}
2.3.4配置gunicorn.py
这个的作用是用gunicorn命令启动django项目时,gunicorn读取配置用的;
此处daemon=True,可以直接实现守护进程启动,比较方便,不用配systemd
# /gunicron.py
bind = '0.0.0.0:8000'
workers = 2
daemon = True
2.4确保redis启动
#查看redis是否启动
redis-cli ping
#启动redis
redis-server
2.5启动celery
此处我用的nohup启动的celery work;也可以使用systemd配置一下;我嫌麻烦,就没有配,之前配systemd的时候,老遇到一些python环境启动的问题,解决起来挺麻烦,所以直接偷懒了。
cd ~/{django项目目录};conda activate {项目的虚拟环境};nohup celery -A map_target_slice worker >/dev/null 2>&1 &
2.6启动django
之前一直使用uwsgi来启动django后端服务,但是uwsgi之前遇到过python3和python2差别的问题;整体配置起来挺麻烦;所以干脆使用django的项目文档中推荐gunicorn;
cd ~/{django项目目录};conda activate {项目的虚拟环境};gunicorn map_target_slice.wsgi:application -c gunicorn.py
至此,项目配置并运行成功