You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Heroku上部署集成Channels与Celery的Django项目?

在Heroku上部署Django + Django Channels + Celery的完整方案

我来帮你搞定这个问题——核心确实是Procfile的配置,因为Channels和Celery都需要worker进程,但Heroku支持定义多个进程类型,完全可以分开启动它们,互不干扰。下面是一步步的实现方案:

1. 编写正确的Procfile

Heroku的Procfile允许你定义多种进程类型,每个类型可以单独启动实例。我们需要为四个核心组件分别配置进程:

# 处理HTTP和WebSocket请求的ASGI服务器(Daphne)
web: daphne your_project.asgi:application --port $PORT --bind 0.0.0.0

# Channels的消费者Worker,处理WebSocket的异步任务
channels_worker: python manage.py runworker

# Celery的任务Worker,处理后台异步任务
celery_worker: celery -A your_project worker -l info

# (可选)Celery Beat,处理定时任务,需要安装django-celery-beat
celery_beat: celery -A your_project beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler

替换其中的your_project为你的Django项目名称即可。

2. 配置依赖包(requirements.txt)

确保你的requirements.txt包含所有必要的依赖:

django>=4.0
daphne>=4.0
channels>=4.0
celery>=5.0
redis>=4.0
django-celery-beat>=2.5  # 如果你需要Celery Beat定时任务的话

这里推荐用Redis作为消息中间件,因为Channels和Celery都能很好地支持它,而且Heroku有官方的Redis插件,配置起来很方便。

3. 配置ASGI和Channels路由

修改项目根目录的asgi.py,确保它同时兼容Django的HTTP请求和Channels的WebSocket请求:

import os
import django
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack

# 设置Django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')
django.setup()

# 导入你的Channels路由文件
import your_project.routing

application = ProtocolTypeRouter({
    # 处理普通HTTP请求
    "http": get_asgi_application(),
    # 处理WebSocket请求,带用户认证
    "websocket": AuthMiddlewareStack(
        URLRouter(
            your_project.routing.websocket_urlpatterns
        )
    ),
})

然后在settings.py里配置Channels的消息层和Celery的相关设置:

# Channels配置
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
        },
    },
}

# Celery配置
CELERY_BROKER_URL = os.environ.get('REDIS_URL', 'redis://localhost:6379')
CELERY_RESULT_BACKEND = os.environ.get('REDIS_URL', 'redis://localhost:6379')
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

4. Heroku部署操作步骤

  1. 安装Heroku CLI并登录你的账号:
    heroku login
    
  2. 创建Heroku应用:
    heroku create your-app-name
    
  3. 添加Redis插件(免费版足够测试):
    heroku addons:create heroku-redis:hobby-dev
    
  4. 设置必要的环境变量(比如Django的密钥、调试模式等):
    heroku config:set DJANGO_SETTINGS_MODULE=your_project.settings
    heroku config:set SECRET_KEY="your-secret-key-here"
    heroku config:set DEBUG=False
    
  5. 推送代码到Heroku:
    git push heroku main
    
  6. 启动各个进程:
    # 启动Web进程(Daphne)
    heroku ps:scale web=1
    # 启动Channels Worker
    heroku ps:scale channels_worker=1
    # 启动Celery Worker
    heroku ps:scale celery_worker=1
    # (可选)启动Celery Beat
    heroku ps:scale celery_beat=1
    

5. 常见问题排查

  • 日志查看:如果某个进程启动失败,用heroku logs --tail实时查看日志,定位问题。
  • Redis连接:用heroku redis:cli测试Redis连接是否正常,确保Channels和Celery用的是同一个Redis实例。
  • 资源限制:Heroku免费版每个进程最多只能启动1个实例,如果需要更高性能,需要升级到付费计划。
  • 进程冲突:确保不要把Channels Worker和Celery Worker混为同一个进程类型,分开定义就能避免冲突。

内容的提问来源于stack exchange,提问作者Alireza Savand

火山引擎 最新活动