使用django-rest-framework如何实现不阻塞客户端请求的定时爬取任务?
解决Django REST Framework项目后台定时爬取任务不阻塞请求的方案
核心逻辑:不要将定时爬取逻辑和DRF的请求处理进程放在同一线程/进程内,必须通过独立的异步任务队列+调度器实现解耦,以下是三种不同场景的可选方案:
方案1:Celery + Celery Beat(生产环境首选)
这是DRF生态最成熟的异步任务解决方案,稳定性强、支持分布式部署
- 安装依赖:
pip install celery django-celery-beat redis(Redis作为消息中间件,也可替换为RabbitMQ) - 基础配置:在项目根目录
__init__.py中注册Celery实例,settings.py中添加CELERY_BROKER_URL、CELERY_RESULT_BACKEND等参数,将django_celery_beat注册到INSTALLED_APPS - 任务封装:新建
tasks.py文件,将爬取逻辑封装为带@shared_task装饰器的函数 - 定时规则配置:运行
python manage.py migrate生成调度规则的数据库表,可直接在Django Admin后台可视化配置每小时执行的规则,也可在代码中写固定调度逻辑 - 启动独立进程:分别启动Celery Worker执行进程和Celery Beat调度进程,两个进程和DRF的Web服务进程完全独立,不会占用Web服务的资源阻塞用户请求
生产环境可以用systemd把Worker和Beat配置为后台守护进程,避免进程意外中断
方案2:Django Q(轻量替代方案,配置成本低)
如果不想搭建复杂的Celery技术栈,可以选择这个和Django生态适配更好的轻量工具
- 安装依赖:
pip install django-q redis - 基础配置:把
django_q添加到INSTALLED_APPS,在settings.py中添加Q_CLUSTER配置指定消息中间件参数 - 定时规则配置:在
Q_CLUSTER的schedule字段中添加爬取任务,设置cron表达式为0 * * * *即可实现每小时执行一次 - 启动独立进程:运行
python manage.py qcluster即可,调度和任务执行都在这个独立进程内,和Web服务完全隔离
方案3:APScheduler(仅适合开发测试/极小流量单机场景)
如果是小型个人项目、不需要分布式部署,可以用这个轻量调度工具直接嵌入Django运行,不需要额外消息中间件
- 安装依赖:
pip install apscheduler - 配置方式:在项目apps.py的AppConfig的ready方法中初始化调度器,添加每小时执行一次的爬取任务
- 启动注意:启动Django服务时需要添加
--noreload参数,命令为python manage.py runserver --noreload,避免Django自动重载机制启动两个重复的调度器
该方案不适合生产多进程部署场景,会出现重复执行任务的问题
内容的提问来源于stack exchange,提问作者Tomas Garrido
相关产品推荐
相关产品推荐

