mirror of
https://github.com/django/daphne.git
synced 2025-07-12 17:02:18 +03:00
Update deployment docs
This commit is contained in:
parent
973b8b72ad
commit
3b8feb5b96
|
@ -34,19 +34,22 @@ serve as the communication layer - for example, the Redis backend connects
|
||||||
to a Redis server. All this goes into the ``CHANNEL_BACKENDS`` setting;
|
to a Redis server. All this goes into the ``CHANNEL_BACKENDS`` setting;
|
||||||
here's an example for a remote Redis server::
|
here's an example for a remote Redis server::
|
||||||
|
|
||||||
CHANNEL_BACKENDS = {
|
CHANNEL_LAYERS = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "channels.backends.redis_py.RedisChannelBackend",
|
"BACKEND": "asgi_redis.RedisChannelLayer",
|
||||||
"HOSTS": [("redis-channel", 6379)],
|
"CONFIG": {
|
||||||
|
"hosts": [("redis-server-name", 6379)],
|
||||||
|
},
|
||||||
|
"ROUTING": "my_project.routing.channel_routing",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
To use the Redis backend you have to install the redis package::
|
To use the Redis backend you have to install it::
|
||||||
|
|
||||||
pip install -U redis
|
pip install -U asgi_redis
|
||||||
|
|
||||||
|
|
||||||
Make sure the same setting file is used across all your workers, interfaces
|
Make sure the same settings file is used across all your workers, interfaces
|
||||||
and WSGI apps; without it, they won't be able to talk to each other and things
|
and WSGI apps; without it, they won't be able to talk to each other and things
|
||||||
will just fail to work.
|
will just fail to work.
|
||||||
|
|
||||||
|
@ -88,44 +91,44 @@ do the work of taking incoming requests and loading them into the channels
|
||||||
system.
|
system.
|
||||||
|
|
||||||
You can just keep running your Django code as a WSGI app if you like, behind
|
You can just keep running your Django code as a WSGI app if you like, behind
|
||||||
something like uwsgi or gunicorn, and just use the WSGI interface as the app
|
something like uwsgi or gunicorn; this won't let you support WebSockets, though.
|
||||||
you load into the server - just set it to use
|
Still, if you want to use a WSGI server and have it talk to a worker server
|
||||||
``channels.interfaces.wsgi:WSGIHandler``.
|
cluster on the backend, see :ref:`wsgi-to-asgi`.
|
||||||
|
|
||||||
If you want to support WebSockets, however, you'll need to run another
|
If you want to support WebSockets, long-poll HTTP requests and other Channels
|
||||||
interface server, as the WSGI protocol has no support for WebSockets.
|
features, you'll need to run a native ASGI interface server, as the WSGI
|
||||||
Channels ships with an Autobahn-based WebSocket interface server
|
specification has no support for running these kinds of requests concurrenctly.
|
||||||
that should suit your needs; however, you could also use a third-party
|
Channels ships with an interface server that we recommend you use called
|
||||||
interface server or write one yourself, as long as it follows the
|
*Daphne*; it supports WebSockets, long-poll HTTP requests, HTTP/2 *(soon)*
|
||||||
:doc:`message-standards`.
|
and performs quite well. Of course, any ASGI-compliant server will work!
|
||||||
|
|
||||||
Notably, it's possible to combine more than one protocol into the same
|
Notably, Daphne has a nice feature where it supports all of these protocols on
|
||||||
interface server, and the one Channels ships with does just this; it can
|
the same port and on all paths; it auto-negotiates between HTTP and WebSocket,
|
||||||
optionally serve HTTP requests as well as WebSockets, though by default
|
so there's no need to have your WebSockets on a separate port or path (and
|
||||||
it will just serve WebSockets and assume you're routing requests to the right
|
they'll be able to share cookies with your normal view code).
|
||||||
kind of server using your load balancer or reverse proxy.
|
|
||||||
|
|
||||||
To run a normal WebSocket server, just run::
|
To run Daphne, it just needs to be supplied with a channel backend;
|
||||||
|
first, make sure your project has an ``asgi.py`` file that looks like this
|
||||||
|
(it should live next to ``wsgi.py``)::
|
||||||
|
|
||||||
python manage.py runwsserver
|
import os
|
||||||
|
from channels.asgi import get_channel_layer
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
|
||||||
|
|
||||||
|
channel_layer = get_channel_layer()
|
||||||
|
|
||||||
|
Then, you can run Daphne and supply the channel layer as the argument:
|
||||||
|
|
||||||
|
daphne my_project.asgi:channel_layer
|
||||||
|
|
||||||
Like ``runworker``, you should place this inside an init system or something
|
Like ``runworker``, you should place this inside an init system or something
|
||||||
like supervisord to ensure it is re-run if it exits unexpectedly.
|
like supervisord to ensure it is re-run if it exits unexpectedly.
|
||||||
|
|
||||||
If you want to enable serving of normal HTTP requests as well, just run::
|
If you only run Daphne and no workers, all of your page requests will seem to
|
||||||
|
hang forever; that's because Daphne doesn't have any worker servers to handle
|
||||||
python manage.py runwsserver --accept-all
|
the request and it's waiting for one to appear (while ``runserver`` also uses
|
||||||
|
Daphne, it launches a worker thread along with it in the same process).
|
||||||
This interface server is built on in-process asynchronous solutions
|
|
||||||
(Twisted for Python 2, and asyncio for Python 3) and so should be able to
|
|
||||||
handle a lot of simultaneous connections. That said, you should still plan to
|
|
||||||
run a cluster of them and load-balance between them; the per-connection memory
|
|
||||||
overhead is moderately high.
|
|
||||||
|
|
||||||
Finally, note that it's entirely possible for interface servers to be written
|
|
||||||
in a language other than Python, though this would mean they could not take
|
|
||||||
advantage of the channel backend abstraction code and so they'd likely be
|
|
||||||
custom-written for a single channel backend.
|
|
||||||
|
|
||||||
|
|
||||||
Deploying new versions of code
|
Deploying new versions of code
|
||||||
|
@ -145,3 +148,7 @@ There's no need to restart the WSGI or WebSocket interface servers unless
|
||||||
you've upgraded your version of Channels or changed any settings;
|
you've upgraded your version of Channels or changed any settings;
|
||||||
none of your code is used by them, and all middleware and code that can
|
none of your code is used by them, and all middleware and code that can
|
||||||
customise requests is run on the consumers.
|
customise requests is run on the consumers.
|
||||||
|
|
||||||
|
You can even use different Python versions for the interface servers and the
|
||||||
|
workers; the ASGI protocol that channel layers communicate over
|
||||||
|
is designed to be very portable and network-transparent.
|
||||||
|
|
|
@ -332,7 +332,8 @@ store it in the session; thankfully, Channels ships with both a ``channel_sessio
|
||||||
decorator that works like the ``http_session_user`` decorator we mentioned above but
|
decorator that works like the ``http_session_user`` decorator we mentioned above but
|
||||||
loads the user from the *channel* session rather than the *HTTP* session,
|
loads the user from the *channel* session rather than the *HTTP* session,
|
||||||
and a function called ``transfer_user`` which replicates a user from one session
|
and a function called ``transfer_user`` which replicates a user from one session
|
||||||
to another.
|
to another. Even better, it combines all of these into a ``channel_session_user_from_http``
|
||||||
|
decorator.
|
||||||
|
|
||||||
Bringing that all together, let's make a chat server where users can only
|
Bringing that all together, let's make a chat server where users can only
|
||||||
chat to people with the same first letter of their username::
|
chat to people with the same first letter of their username::
|
||||||
|
@ -343,8 +344,7 @@ chat to people with the same first letter of their username::
|
||||||
from channels.auth import http_session_user, channel_session_user, transfer_user
|
from channels.auth import http_session_user, channel_session_user, transfer_user
|
||||||
|
|
||||||
# Connected to websocket.connect
|
# Connected to websocket.connect
|
||||||
@channel_session
|
@channel_session_user_from_http
|
||||||
@http_session_user
|
|
||||||
def ws_add(message):
|
def ws_add(message):
|
||||||
# Copy user from HTTP to channel session
|
# Copy user from HTTP to channel session
|
||||||
transfer_user(message.http_session, message.channel_session)
|
transfer_user(message.http_session, message.channel_session)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user