使用Django + Celery时,使用带有SSL的Redis作为代理
这篇文章是Django Advent Calendar 2017和しむどん Advent Calendar 2017第一天的文章。
这里将介绍使用带有SSL的Redis作为Celery的代理以及Django + Celery的配置示例。
总结一下
-
- Celeryのデフォルトの設定ではCeleryでブローカーにSSL有りのRedisを使えません。
-
- SSL有りのRedisを使うには次の設定が必要です。
BROKER_USE_SSL: ブローカーとの接続とSSL設定のSSL使用を切り替えます。 例: {‘ssl_cert_reqs’: ‘none’}
CELERY_REDIS_BACKEND_USE_SSL: Redisがブローカーの場合はこの設定も必要です。例: {‘ssl_cert_reqs’: ssl.CERT_CERT_REQUIRED (sslは標準ライブラリのssl)
Django + Celeryの設定例を https://github.com/TakesxiSximada/TIL/master/django/django-celery-redis-ssl に示しました。
背景 – Background
如果在Azure Redis Cache使用标准方案,则需要分配全局IP才能访问。需要进行密码设置等操作才能使用,同时还需要启用SSL。将带有SSL的Redis指定为Celery的代理商时,使用Celery的默认配置会在与代理商连接时出错。虽然Celery的文档中当然有描述,但Celery的配置项非常多,很难理解。而且解释本身就是对功能的说明,所以很难理解如何使用。因此,在本文中,我们假设在场景中使用Django + Celery的组合,并根据示例代码进行解释。在其中,我们将解释如何将带有SSL的Redis指定为Celery的代理商。
环境
要求
为了执行,我使用了以下的库。这些库是明确使用的。
celery
custom_settings
django
ipdb
redis
以下是包含实际安装的依赖库的列表。
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt requirements.in
#
amqp==2.2.2 # via kombu
appnope==0.1.0 # via ipython
billiard==3.5.0.3 # via celery
celery==4.1.0
custom-settings==1.0.post1
decorator==4.1.2 # via ipython, traitlets
django==1.11.6
ipdb==0.10.3
ipython-genutils==0.2.0 # via traitlets
ipython==6.2.1 # via ipdb
jedi==0.11.0 # via ipython
kombu==4.1.0 # via celery
parso==0.1.0 # via jedi
pexpect==4.2.1 # via ipython
pickleshare==0.7.4 # via ipython
prompt-toolkit==1.0.15 # via ipython
ptyprocess==0.5.2 # via pexpect
pygments==2.2.0 # via ipython
pytz==2017.2 # via celery, django
redis==2.10.6
simplegeneric==0.8.1 # via ipython
six==1.11.0 # via custom-settings, prompt-toolkit, traitlets
traitlets==4.3.2 # via ipython
vine==1.1.4 # via amqp
wcwidth==0.1.7 # via prompt-toolkit
zope.dottedname==4.2 # via custom-settings
创建Django项目
我会创建一个Django项目。项目的名称将设为proj。
django-admin startproject proj .
celeryconfig.py 的中文翻译为:芹菜配置.py
在 celeryconfig.py 文件中,我们记录了 Celery 的配置。首先,我们指定了代理人、用于保存返回值的后端以及用于数据传递的格式。如果使用 Celery,这些是必需的设置。在这里使用的 custom_settings 是用于配置的辅助库。更多详细信息请参考 https://pypi.python.org/pypi/custom_settings。
import custom_settings
custom = custom_settings.load('settings_custom')
BROKER_URL = custom.get('BROKER_URL', default='redis://:REDIS_PASS@localhost:6379/0')
CELERY_RESULT_BACKEND = custom.get('BROKER_URL', default='redis://:REDIS_PASS@localhost:6379/0')
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
接下来是配置SSL连接。我们要设置BROKER_USE_SSL和CELERY_REDIS_BACKEND_USE_SSL。
import ssl
BROKER_USE_SSL = {'ssl_cert_reqs': 'none'}
CELERY_REDIS_BACKEND_USE_SSL = {'ssl_cert_reqs': ssl.CERT_REQUIRED}
整体情况如下。
# <CELERY-BASE>
import custom_settings
custom = custom_settings.load('settings_custom')
BROKER_URL = custom.get('BROKER_URL', default='redis://:REDIS_PASS@localhost:6379/0')
CELERY_RESULT_BACKEND = custom.get('BROKER_URL', default='redis://:REDIS_PASS@localhost:6379/0')
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
# </CELERY-BASE>
# <CELERY-SSL>
import ssl
BROKER_USE_SSL = {'ssl_cert_reqs': 'none'}
CELERY_REDIS_BACKEND_USE_SSL = {'ssl_cert_reqs': ssl.CERT_REQUIRED}
# </CELERY-SSL>
准备芹菜。
我们将在之前创建的proj项目中使用Celery。首先,我们要创建proj/celery_.py文件,并按照以下内容填写。
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
# <CELERY-APP>
app = Celery('proj')
app.config_from_object('celeryconfig')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
# </CELERY-APP>
# <CELERY-TASK>
@app.task
def debug():
print('OK')
# </CELERY-TASK>
创建和配置Celery对象。
app = Celery('proj')
app.config_from_object('celeryconfig')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
使用 app.config_from_object(‘celeryconfig’) 将读取配置。本次将在 celeryconfig.py 文件中描述 Celery 的配置。对于 Django,也可以在 proj/settings.py 中进行类似的配置,并将 app.config_from_obj(‘celeryconfig’) 的第一个参数设置为 ‘django.conf:settings’,效果是一样的。
我会定义一个任务以进行验证。稍后我会使用 celery call 命令调用这个任务。
@app.task
def debug():
print('OK')
请确认行动。
创建执行环境。在这里我们省略了venv等,请根据需要适应创建。安装依赖库。
pip install -r requirements.txt
サンプルコードはDjangoプロジェクトなのでマイグレーションを実行します。
python manage.py migrate
Celeryワーカーを起動します。ワーカー起動は -D を付けているのでバックグラウンドで実行します。 –logfile で指定したファイルにログを出力します。
celery -A proj.celery_app worker -D --pidfile .worker.pid --logfile worker.log
我已经准备好了。我已经将proj.celery_.debug实现为一个用于调试的任务。现在将执行该任务。
celery -A proj.celery_app call proj.celery_.debug
以下是显示的哈希值。这表示任务已被注册到Redis并且工作程序的处理已完成。
$ celery -A proj.celery_app call proj.celery_.debug
b77a6165-4458-4540-a3a7-0824f4d6ca30
如果哈希值未显示,那么可能存在错误的部分。请特别检查以下项目。
-
- Redisは起動しているか?
-
- Redisへの接続情報は間違っていないか?
- 設定ファイルの記述は正しいか?
整理收拾
由于工作进程仍在运行状态,将停止它。工作进程在启动时使用–pidfile选项指定了一个文件来输出进程ID。您可以使用kill命令来关闭该进程。
kill `cat .worker.pid`
请提供一份参考。
-
- http://docs.celeryproject.org/en/latest/userguide/configuration.html
- https://qiita.com/kawasin73/items/76a22712817ff2a23777