Django3.2.15+Celery5.1.2定时任务配置后无执行问题求助
Django + Celery + django-celery-beat 定时任务无响应排查
问题概述
使用 Django3.2.15、Celery v5.1.2 和 django-celery-beat2.2.1 搭建定时任务,已在 admin 后台将 hello_world 任务设置为15秒执行间隔,成功启动 Celery Worker 和 Beat,但修改任务或调度后,所有终端均无任何反应。
配置文件与启动日志
mysite.settings
""" Django settings for mysite project. Generated by 'django-admin startproject' using Django 2.1. For more information on this file, see https://docs.djangoproject.com/en/2.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.1/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'your_secret_key_here' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'correlator.apps.CorrelatorConfig', 'reviews.apps.ReviewsConfig', 'parameters.apps.ParametersConfig', 'trex', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', #'django_filters', 'rest_framework_swagger', # optional, creates browsable API docs 'easy_thumbnails', # Required by `content_image` plugin 'celery', 'django_celery_beat', 'iris', 'django_celery_results', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'mysite.mycsrfmiddleware.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'mysite.mymiddleware.CorrelatorControllerMiddleware', ] ROOT_URLCONF = 'mysite.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'mysite.wsgi.application' # Database # https://docs.djangoproject.com/en/2.1/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'postgres', 'USER': 'postgres', 'PASSWORD': 'M@ster449644p', 'HOST': 'localhost', 'PORT': '5432', } } # Password validation # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.1/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True CSRF_TRUSTED_ORIGINS = ["http://localhost:8000"] #CSRF_COOKIE_DOMAIN = '.localhost' # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.1/howto/static-files/ STATIC_URL = '/static/' MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler' # # Celery Broker - Redis CELERY_BROKER_URL = 'amqp://localhost' # Celery Configuration Options CELERY_TASK_TRACK_STARTED = True CELERY_TASK_TIME_LIMIT = 30 * 60 CELERY_CACHE_BACKEND = 'django-cache' # CELERY_ACCEPT_CONTENT = ['application/json'] # CELERY_TASK_SERIALIZER = 'json' # CELERY_RESULT_SERIALIZER = 'json' CELERY_RESULT_BACKEND = 'django-db' CELERY_TIMEZONE = "Asia/HongKnong"
mysite.celery.py
from __future__ import absolute_import, unicode_literals import os from celery import Celery import requests from django.utils import timezone #from celery.contrib import rdb # set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') app = Celery('mysite') # Optional configuration, see the application user guide. app.conf.update( result_expires=3600, ) if __name__ == '__main__': app.start() # Using a string here means the worker doesn'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', namespace='CELERY') # Load task modules from all registered Django app configs. app.autodiscover_tasks() @app.task(bind=True) def debug_task(self): print('Request: {0!r}'.format(self.request)) @app.task(bind=True) def hello_world(self): print('Hello world!')
启动日志
Celery Worker启动命令及日志
celery -A mysite worker -l INFO -P gevent celery@DESKTOP-65V2VTJ v5.1.2 (sun-harmonics) --- ***** ----- -- ******* ---- Windows-10-10.0.19041-SP0 2022-10-31 15:33:23 - *** --- * --- - ** ---------- [config] - ** ---------- .> app: mysite:0x28bba8b0ef0 - ** ---------- .> transport: amqp://guest:**@localhost:5672// - ** ---------- .> results: - *** --- * --- .> concurrency: 12 (gevent) -- ******* ---- .> task events: ON--- ***** ----- -------------- [queues] .> celery exchange=celery(direct) key=celery [tasks] . correlator.tasks.add . correlator.tasks.mul . iris.tasks.add . iris.tasks.mul . mysite.celery.debug_task . mysite.celery.hello_world . reviews.tasks.add . reviews.tasks.mul . reviews.tasks.rename_widget [2022-10-31 15:33:23,540: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672// [2022-10-31 15:33:23,544: INFO/MainProcess] mingle: searching for neighbors [2022-10-31 15:33:24,564: INFO/MainProcess] mingle: all alone [2022-10-31 15:33:24,573: WARNING/MainProcess] c:\users\mikeoliver\github\correlator-2\venv\lib\site-packages\celery\fixups\django.py:204: UserWarning: Using settings.DEBUG leads to a memory leak, never use this setting in production environments! leak, never use this setting in production environments!''') [2022-10-31 15:33:24,574: INFO/MainProcess] celery@DESKTOP-65V2VTJ ready. [2022-10-31 15:33:24,577: INFO/MainProcess] pidbox: Connected to amqp://guest:**@127.0.0.1:5672//.
Celery Beat启动命令及日志
celery beat celery beat v5.1.2 (sun-harmonics) is starting. __ - ... __ - _ LocalTime -> 2022-10-31 15:34:11 Configuration -> . broker -> amqp://guest:**@localhost:5672// . loader -> celery.loaders.default.Loader . scheduler -> celery.beat.PersistentScheduler . db -> celerybeat-schedule . logfile -> [stderr]@%WARNING . maxinterval -> 5.00 minutes (300s)
排查与解决步骤
1. 修复 Celery Beat 启动命令
从 Beat 日志可以看到,当前使用的是默认的 PersistentScheduler(文件调度器),而非配置中指定的 DatabaseScheduler,原因是启动 Beat 时未关联 Django 应用实例,导致无法读取 admin 后台配置的数据库任务。
正确启动命令:
celery -A mysite beat -l INFO
2. 修正时区拼写错误
settings.py 中 CELERY_TIMEZONE = "Asia/HongKnong" 存在拼写错误,正确应为 Asia/Hong_Kong。时区不匹配会导致任务调度时间计算偏差,无法按时触发。
修改配置:
# settings.py CELERY_TIMEZONE = "Asia/Hong_Kong" TIME_ZONE = "Asia/Hong_Kong" # 保持Django时区与Celery一致
3. 验证后台任务配置
进入 Django admin 的Periodic tasks页面,确认:
Task (registered)字段选择的是mysite.celery.hello_world- 关联的Interval Schedule已设置为15秒
- 任务的
Enabled选项已勾选
4. 重启服务生效
修改配置或任务后,必须重启 Worker 和 Beat:
# 重启Worker celery -A mysite worker -l INFO -P gevent # 重启Beat(使用正确命令) celery -A mysite beat -l INFO
5. 检查消息队列状态
通过 RabbitMQ 管理界面(默认端口15672)查看 celery 队列:
- 如果队列无消息:说明 Beat 未生成任务,检查 Beat 启动命令和数据库调度器配置
- 如果队列有消息但 Worker 未消费:检查 Worker 是否正常连接到 RabbitMQ
内容的提问来源于stack exchange,提问作者Mike Oliver
相关产品推荐
相关产品推荐

