使用 django 频道的 heroku 的正确 procfile / 要求是啥?

Posted

技术标签:

【中文标题】使用 django 频道的 heroku 的正确 procfile / 要求是啥?【英文标题】:What's the right procfile / requirements for heroku with django channels?使用 django 频道的 heroku 的正确 procfile / 要求是什么? 【发布时间】:2020-08-15 13:11:25 【问题描述】:

tl;dr - django 频道应用使用 manage.py runserver 在本地运行,但不在 heroku 上。

我是 django 频道的新手 - 尝试使用 heroku 频道部署一个非常基本的 django 应用程序。我最初使用标准django polls tutorial 构建项目并将其部署到heroku。然后我使用django channels tutorial 添加了一个聊天应用程序。按照他们的建议和“python manage.py runserver”,使用 docker 来运行 redis 服务器,设法在本地正常运行。

我在尝试将其部署到 heroku 或使用 heroku local 在本地运行时遇到了困难。我已经在 heroku 中添加了 redis 插件并修改了 settings.py 以指向 REDIS_URL 环境变量。如果合适,我还修改了我的模板以使用 wss(我相信这对于 heroku 来说是必要的):

var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
        var target = ws_scheme + '://'
        + window.location.host
        + '/ws/chat/'
        + roomName
        + '/';
        const chatSocket = new WebSocket(
          target
        );
...

因此,我得出的结论是问题出在 procfile 上。我不确定那里的使用说明是什么。最初使用的投票教程:

web: gunicorn gettingstarted.wsgi --log-file -

如果我只是使用'heroku local' 工作正常并且部署工作正常,但是当我尝试发送聊天消息时它什么也不做并且在控制台中显示 404。我知道我必须将其更改为使用 asgi 服务器而不是 gunicorn。发现 this tutorial 在部署一个带有通道到 heroku 的应用程序时,它使用了:

web: daphne chat.asgi:channel_layer --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker -v2

我试过了,但这就是我卡住的地方。这是我在本地运行 heroku 时得到的结果:

krishnas-air:python-getting-started Krishna$ heroku local
[OKAY] Loaded ENV .env File as KEY=VALUE Format
6:46:50 PM worker.1 |  Traceback (most recent call last):
6:46:50 PM worker.1 |    File "manage.py", line 8, in <module>
6:46:50 PM worker.1 |      from django.core.management import execute_from_command_line
6:46:50 PM worker.1 |  ImportError: No module named django.core.management
[DONE] Killing all processes with signal  SIGINT
6:46:50 PM worker.1 Exited with exit code null
6:46:50 PM web.1    |  Traceback (most recent call last):
6:46:50 PM web.1    |    File "/usr/local/bin/daphne", line 5, in <module>
6:46:50 PM web.1    |      from daphne.cli import CommandLineInterface
6:46:50 PM web.1    |    File "/usr/local/lib/python3.7/site-packages/daphne/cli.py", line 1, in <module>
6:46:50 PM web.1    |      import argparse
6:46:50 PM web.1    |    File "<frozen importlib._bootstrap>", line 983, in _find_and_load
6:46:50 PM web.1    |    File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
6:46:50 PM web.1    |    File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
6:46:50 PM web.1    |    File "<frozen importlib._bootstrap_external>", line 724, in exec_module
6:46:50 PM web.1    |    File "<frozen importlib._bootstrap_external>", line 857, in get_code
6:46:50 PM web.1    |    File "<frozen importlib._bootstrap_external>", line 525, in _compile_bytecode
6:46:50 PM web.1    |  KeyboardInterrupt
6:46:50 PM web.1    Exited with exit code null

导入错误消息让我觉得我的 requirements.txt 可能遗漏了一些东西,因此我也将其包含在此处以供参考:

django
gunicorn
django-heroku
requests
channels
channels_redis
asgi_redis
asgiref
daphne
redis
gevent
gevent-websocket
greenlet

感谢您的帮助!

【问题讨论】:

你能显示你的chat.asgi文件的内容吗? 【参考方案1】:

我刚刚发现了一个非常相似的问题。首先,虽然不是 Heroku 特有的,但这些 docs 是必读的。

我认为问题在于 Heroku 通过 WSGI 而不是 ASGI 路由 ws:// 请求。所以第一步是在与wsgi.py 相同的文件夹中创建一个asgi.py 文件,如下所示:

import django
from channels.routing import get_default_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dropdjango.settings")
django.setup()
application = get_default_application()

然后,在 Procfile 中,为 web worker 定义 dynos:

web: daphne <my-web-app>.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channel_layer -v2

如果 Heroku 中尚不存在测功机,请使用 Heroku CLI 创建它们。 就我而言,web dyno 已经存在,所以我只创建了 worker dyno:

heroku ps:scale worker=1:free -a <your-heroku-app-name>

最后,仔细检查您的 settings.py 以确保您拥有:

ASGI_APPLICATION="<my-web-app>.routing.application"
CHANNEL_LAYERS = 
    "default": 
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": "hosts": [os.environ.get("REDIS_URL", "redis://localhost:6379")],
    ,

警告:这将通过 daphne 运行您的所有请求。我读过警告,但我还没有经历过。

【讨论】:

我在本地一切正常(我在其他地方的 ASGI 设置相同)但只是想知道 worker: 代码行。如果它有效,将对此表示赞同。我的意思是你提到的其余内容很有意义,因为 CHANNEL_LAYERS 已经在设置中声明,worker 调用它。 您好。 CHANEL_LAYERS 配置字典只是将 redis 定义为后端。工作进程文件(Procfile)中的channel_layerpython manage.py runworker 函数的参数。此参数表示工作人员将要收听的频道的名称。 github.com/django/channels/blob/master/channels/management/…你可以在中看到 只是好奇,-v2 在 procfile 中做了什么? $PORT 环境变量呢?在生产环境中运行它不是首选吗? @RoastBiter -v2 将详细程度设置为最大,因为 heroku 希望您的网络服务器侦听的端口很可能与 daphne 的默认值不匹配,因此您需要覆盖它。

以上是关于使用 django 频道的 heroku 的正确 procfile / 要求是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Django频道使用redis设置在heroku泄漏内存

如何在 Heroku 上使用 Channels 和 Celery 部署 Django?

在 Heroku 上部署 Django/静态文件的正确方法

安装频道:Python Django 版本和设置

Heroku 上带有 Postgresql 的 Django - settings.DATABASES 配置不正确。请提供名称值

如何从 Heroku 上的 Django 项目正确地提供我的 Angular 应用程序静态文件?