Развертывание

Приложения Channels (ASGI) развертываются аналогично приложениям WSGI - вы загружаете их на сервер, такой как Daphne, и можете масштабировать количество серверных процессов вверх и вниз.

Единственным необязательным дополнительным требованием для проекта Channels является предоставление channel layer. Оба шага описаны ниже.

Настройка приложения ASGI

Как обсуждалось в Установка и Маршрутизация, у вас будет файл типа myproject/asgi.py, который будет определять ваше корневое приложение. Почти наверняка это будет ваш маршрутизатор верхнего уровня (тип протокола).

Вот пример того, как может выглядеть asgi.py:

import os

from django.conf.urls import url
from django.core.asgi import get_asgi_application

# Fetch Django ASGI application early to ensure AppRegistry is populated
# before importing consumers and AuthMiddlewareStack that may import ORM
# models.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
django_asgi_app = get_asgi_application()

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter

from chat.consumers import AdminChatConsumer, PublicChatConsumer

application = ProtocolTypeRouter({
    # Django's ASGI application to handle traditional HTTP requests
    "http": django_asgi_app,

    # WebSocket chat handler
    "websocket": AuthMiddlewareStack(
        URLRouter([
            url(r"^chat/admin/$", AdminChatConsumer.as_asgi()),
            url(r"^chat/$", PublicChatConsumer.as_asgi()),
        ])
    ),
})

Настройка бэкенда канала

Примечание

Этот шаг необязателен. Если вы не используете слой канала, пропустите этот раздел.

Обычно бэкенд канала подключается к одному или нескольким центральным серверам, которые служат в качестве коммуникационного уровня - например, бэкенд Redis подключается к серверу Redis. Все это входит в настройку CHANNEL_LAYERS; вот пример для удаленного сервера Redis:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("redis-server-name", 6379)],
        },
    },
}

Чтобы использовать бэкенд Redis, необходимо установить его:

pip install -U channels_redis

Запуск серверов протоколов

Чтобы общаться с внешним миром, ваше приложение Channels/ASGI должно быть загружено в протокольный сервер. Они могут быть похожи на серверы WSGI и запускать ваше приложение в режиме HTTP, но они также могут соединяться с любым количеством других протоколов (протоколы чата, протоколы IoT, даже радиосети).

Все эти серверы имеют свои собственные параметры конфигурации, но у них есть одна общая черта - они хотят, чтобы вы передали им ASGI-приложение для запуска. Все, что вам нужно сделать, это передать объект application внутри файла asgi.py вашего проекта протокольному серверу в качестве приложения, которое он должен запустить:

daphne -p 8001 myproject.asgi:application

HTTP и WebSocket

Хотя ASGI является общим протоколом, и мы не можем охватить здесь все возможные серверы, вполне вероятно, что вы захотите развернуть проект Channels для работы через HTTP и, возможно, WebSocket, поэтому мы рассмотрим это более подробно.

Проект Channels поддерживает официальный ASGI HTTP/WebSocket сервер, Daphne, и именно о его настройке мы и поговорим. Другие HTTP/WebSocket ASGI-серверы возможны и будут работать так же хорошо, если они соответствуют спецификации, но будут иметь другую конфигурацию.

Вы можете использовать Daphne для всех запросов - HTTP и WebSocket - или, если вы консервативны в вопросах стабильности, продолжать выполнять стандартные HTTP-запросы через WSGI-сервер и использовать Daphne только для того, что WSGI не может делать, например, HTTP long-polling и WebSockets. Если вы сделаете разделение, вам нужно будет поставить что-то перед Daphne и вашим WSGI-сервером, чтобы определить, какие запросы посылать каждому (используя HTTP-путь или домен) - это не рассматривается здесь, просто знайте, что вы можете это сделать.

Если вы используете Daphne для всего трафика, он автоматически переключается между HTTP и WebSocket, поэтому нет необходимости располагать ваши WebSockets на отдельном домене или пути (и они смогут обмениваться cookies с вашим обычным кодом представления, что невозможно, если вы разделяете их по домену, а не по пути).

Чтобы запустить Daphne, его нужно просто поставить вместе с приложением, точно так же, как это нужно сделать серверу WSGI. Убедитесь, что у вас есть файл asgi.py, как описано выше.

Затем вы можете запустить Daphne и указать в качестве аргумента приложение ASGI:

daphne myproject.asgi:application

Вам следует запускать Daphne внутри супервизора процессов (systemd, supervisord) или системы оркестровки контейнеров (kubernetes, nomad), чтобы обеспечить его перезапуск при необходимости и позволить вам масштабировать количество процессов.

Если вы хотите привязать несколько экземпляров Daphne к одному порту на машине, используйте супервизор процессов, который может прослушивать порты и передавать дескрипторы файлов запущенным процессам, а затем передавать дескриптор файла с помощью --fd NUM.

Вы также можете указать порт и IP, к которым привязывается Daphne:

daphne -b 0.0.0.0 -p 8001 myproject.asgi:application

Вы можете узнать больше о Daphne и ее возможностях on GitHub.

Альтернативные веб-серверы

Существуют также альтернативные серверы ASGI, которые вы можете использовать для обслуживания каналов.

В какой-то степени веб-серверы ASGI должны быть взаимозаменяемыми, все они должны обладать одинаковой базовой функциональностью в плане обслуживания HTTP и WebSocket запросов.

Аспекты, в которых серверы могут различаться, - это их конфигурация и настройки по умолчанию, характеристики производительности, поддержка ограничения ресурсов, различия в поддержке протоколов и сокетов, а также подходы к управлению процессами.

Вы можете увидеть больше альтернативных серверов, таких как Uvicorn, в ASGI implementations documentation.

Примеры установок

Это примеры возможных настроек - не гарантируется, что они будут работать из коробки, и их следует воспринимать скорее как руководство, чем как прямой учебник.

Nginx/Супервизор (Ubuntu)

Этот пример устанавливает сайт Django на сервере Ubuntu, используя Nginx в качестве основного веб-сервера и supervisord для запуска и управления Daphne.

Сначала установите Nginx и Supervisor:

$ sudo apt install nginx supervisor

Теперь вам нужно создать файл конфигурации супервизора (часто расположенный в /etc/supervisor/conf.d/ - здесь мы заставляем супервизор прослушивать TCP-порт, а затем передаем этот сокет дочерним процессам, чтобы все они могли использовать один и тот же связанный порт:

[fcgi-program:asgi]
# TCP socket used by Nginx backend upstream
socket=tcp://localhost:8000

# Directory where your site's project files are located
directory=/my/app/path

# Each process needs to have a separate socket file, so we use process_num
# Make sure to update "mysite.asgi" to match your project name
command=daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers mysite.asgi:application

# Number of processes to startup, roughly the number of CPUs you have
numprocs=4

# Give each process a unique name so they can be told apart
process_name=asgi%(process_num)d

# Automatically start and recover processes
autostart=true
autorestart=true

# Choose where you want your log to go
stdout_logfile=/your/log/asgi.log
redirect_stderr=true

Создайте каталог запуска для сокетов, на которые ссылается файл конфигурации супервизора.

$ sudo mkdir /run/daphne/

При запуске супервизорной fcgi-программы под другим пользователем измените настройки владельца каталога запуска.

$ sudo chown <user>.<group> /run/daphne/

Папка /run/ очищается при перезагрузке сервера. Чтобы сделать папку /run/daphne постоянной, создайте файл /usr/lib/tmpfiles.d/daphne.conf с содержимым, приведенным ниже.

$ d /run/daphne 0755 <user> <group>

Поручите руководителю перечитать и обновить свои задания:

$ sudo supervisorctl reread
$ sudo supervisorctl update

Примечание

Выполнение команды daphe с --fd 0 в командной строке завершится неудачей и приведет к [Errno 88] Socket operation on non-socket.

Supervisor будет автоматически создавать сокет, связывать и прослушивать перед форкингом первого дочернего устройства в группе. Сокет будет передан каждому ребенку в файловом дескрипторе под номером 0 (ноль). См. http://supervisord.org/configuration.html#fcgi-program-x-section-settings

Далее необходимо указать Nginx, чтобы он проксировал трафик на запущенные экземпляры Daphne. Настройте файл nginx upstream conf для вашего проекта:

upstream channels-backend {
    server localhost:8000;
}
...
server {
    ...
    location / {
        try_files $uri @proxy_to_app;
    }
    ...
    location @proxy_to_app {
        proxy_pass http://channels-backend;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
    }
    ...
}

Перезагрузите nginx, чтобы применить изменения:

$ sudo service nginx reload
Вернуться на верх