You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+Celery+Scrapy架构遇ReactorNotRestartable及数据库SSL错误求助

解决Django+Celery+Scrapy组合中的ReactorNotRestartable与数据库SSL错误

嘿,我刚好踩过类似的坑,这俩问题确实挺磨人的,我给你一步步拆解解决:

一、搞定ReactorNotRestartable错误

这个问题的核心逻辑是:Celery是长生命周期进程,而Scrapy依赖的Twisted Reactor一旦启动并停止后,同一个进程里根本没法再次重启。当Celery重复调用你的自定义Django命令时,就会触发这个报错。

最优方案:用多进程隔离Scrapy运行环境

每次Celery任务触发时,启动一个全新的进程来执行Scrapy爬虫,这样每个进程的Reactor都是独立的,完全不会有重启冲突。给你两种实现方式:

方式1:Celery任务中用subprocess调用Django命令

from celery import shared_task
import subprocess
import sys

@shared_task
def scheduled_crawl_task():
    # 用当前Python环境执行自定义命令,避免环境不一致问题
    subprocess.run(
        [sys.executable, "manage.py", "get_data"],
        check=True,
        capture_output=True,
        text=True
    )

方式2:用multiprocessing封装命令调用

from celery import shared_task
from multiprocessing import Process
from django.core.management import call_command

@shared_task
def scheduled_crawl_task():
    # 启动新进程执行爬虫命令
    crawl_process = Process(target=call_command, args=("get_data",))
    crawl_process.start()
    crawl_process.join()

备选方案:改用CrawlerRunner替代CrawlerProcess

如果你不想用多进程,也可以修改自定义命令里的Scrapy启动逻辑,用CrawlerRunner代替CrawlerProcess(它不会自动管理Reactor的启动/停止):

from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging
from twisted.internet import reactor
from scrapy.settings import Settings
import crawler_settings  # 你的Scrapy配置模块

class Command(BaseCommand):
    help = 'Crawl for new data'

    def handle(self, *args, **options):
        configure_logging()
        settings = Settings()
        settings.setmodule(crawler_settings)
        
        runner = CrawlerRunner(settings)
        # 替换成你的Spider类
        deferred = runner.crawl(YourSpiderClass)
        
        # 爬虫结束后手动停止Reactor
        deferred.addBoth(lambda _: reactor.stop())
        reactor.run()

⚠️ 提醒:这种方式如果在同一个Celery worker进程中多次调用,还是可能触发Reactor错误,所以更推荐前面的多进程方案。

二、解决数据库SSL错误

这个错误基本是Django数据库配置和数据库服务器的SSL要求不匹配导致的,分两种场景处理:

场景1:生产环境数据库要求SSL连接

根据你用的数据库类型,修改settings.py中的DATABASES配置,添加SSL相关参数:

PostgreSQL示例:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'your_db_name',
        'USER': 'your_db_user',
        'PASSWORD': 'your_db_password',
        'HOST': 'your_db_host',
        'PORT': '5432',
        'OPTIONS': {
            # 按数据库要求选sslmode:require/verify-ca/verify-full
            'sslmode': 'require',
            # 如果需要验证证书,替换成你的证书路径
            # 'sslrootcert': '/etc/ssl/certs/ca-certificates.crt',
            # 'sslcert': '/path/to/client-cert.pem',
            # 'sslkey': '/path/to/client-key.pem',
        },
    }
}

MySQL示例:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'your_db_name',
        'USER': 'your_db_user',
        'PASSWORD': 'your_db_password',
        'HOST': 'your_db_host',
        'PORT': '3306',
        'OPTIONS': {
            'ssl': {
                'ca': '/path/to/ca.pem',
                'cert': '/path/to/client-cert.pem',
                'key': '/path/to/client-key.pem'
            }
        },
    }
}

场景2:本地开发环境无需SSL

如果是本地测试用的数据库(比如Docker里的实例)没开SSL要求,直接去掉SSL相关配置,或者明确禁用:

# PostgreSQL禁用SSL
'OPTIONS': {'sslmode': 'disable'}

最后验证

  1. 启动Celery worker:celery -A your_project_name worker --loglevel=info
  2. 在Django shell中调用scheduled_crawl_task.delay()触发测试任务
  3. 查看日志,确认爬虫正常运行且数据成功存入数据库

内容的提问来源于stack exchange,提问作者Levi Moreira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:36:48