mirror of
https://github.com/django/daphne.git
synced 2025-07-11 08:22:17 +03:00
Update backends docs, remove old message standards
This commit is contained in:
parent
d452486524
commit
3dec8e09b3
|
@ -6,18 +6,6 @@ Draft ASGI Spec
|
||||||
considered draft yet. Even the name might change; this is being written
|
considered draft yet. Even the name might change; this is being written
|
||||||
as development progresses.**
|
as development progresses.**
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
PEP: XXX
|
|
||||||
Title: ASGI (Asynchronous Server Gateway Interface)
|
|
||||||
Version: $Revision$
|
|
||||||
Last-Modified: $Date$
|
|
||||||
Author: Andrew Godwin <andrew@aeracode.org>
|
|
||||||
Status: Draft
|
|
||||||
Type: Informational
|
|
||||||
Content-Type: text/x-rst
|
|
||||||
Created: ?
|
|
||||||
Post-History: ?
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
========
|
========
|
||||||
|
|
|
@ -1,28 +1,34 @@
|
||||||
Backends
|
Channel Layer Types
|
||||||
========
|
===================
|
||||||
|
|
||||||
Multiple choices of backend are available, to fill different tradeoffs of
|
Multiple choices of backend are available, to fill different tradeoffs of
|
||||||
complexity, throughput and scalability. You can also write your own backend if
|
complexity, throughput and scalability. You can also write your own backend if
|
||||||
you wish; the API is very simple and documented below.
|
you wish; the spec they confirm to is called :doc:`ASGI <asgi>`. Any
|
||||||
|
ASGI-compliant channel layer can be used.
|
||||||
|
|
||||||
Redis
|
Redis
|
||||||
-----
|
-----
|
||||||
|
|
||||||
The Redis backend is the recommended backend to run Channels with, as it
|
The Redis layer is the recommended backend to run Channels with, as it
|
||||||
supports both high throughput on a single Redis server as well as the ability
|
supports both high throughput on a single Redis server as well as the ability
|
||||||
to run against a set of Redis servers in a sharded mode.
|
to run against a set of Redis servers in a sharded mode.
|
||||||
|
|
||||||
To use the Redis backend you have to install the redis package::
|
To use the Redis layer, simply install it from PyPI (it lives in a separate
|
||||||
|
package, as we didn't want to force a dependency on the redis-py for the main
|
||||||
|
install):
|
||||||
|
|
||||||
pip install -U redis
|
pip install -U asgi_redis
|
||||||
|
|
||||||
By default, it will attempt to connect to a Redis server on ``localhost:6379``,
|
By default, it will attempt to connect to a Redis server on ``localhost:6379``,
|
||||||
but you can override this with the ``HOSTS`` setting::
|
but you can override this with the ``hosts`` key in its config::
|
||||||
|
|
||||||
CHANNEL_BACKENDS = {
|
CHANNEL_LAYERS = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "channels.backends.redis_py.RedisChannelBackend",
|
"BACKEND": "asgi_redis.RedisChannelLayer",
|
||||||
"HOSTS": [("redis-channel-1", 6379), ("redis-channel-2", 6379)],
|
"ROUTING": "???",
|
||||||
|
"CONFIG": {
|
||||||
|
"hosts": [("redis-channel-1", 6379), ("redis-channel-2", 6379)],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,72 +55,38 @@ settings. Any misconfigured interface server or worker will drop some or all
|
||||||
messages.
|
messages.
|
||||||
|
|
||||||
|
|
||||||
In-memory
|
|
||||||
---------
|
|
||||||
|
|
||||||
The in-memory backend is the simplest, and not really a backend as such;
|
|
||||||
it exists purely to enable Django to run in a "normal" mode where no Channels
|
|
||||||
functionality is available, just normal HTTP request processing. You should
|
|
||||||
never need to set it explicitly.
|
|
||||||
|
|
||||||
This backend provides no network transparency or non-blocking guarantees.
|
|
||||||
|
|
||||||
Database
|
Database
|
||||||
--------
|
--------
|
||||||
|
|
||||||
=======
|
The database layer is intended as a short-term solution for people who can't
|
||||||
Writing Custom Backends
|
use a more production-ready layer (for example, Redis), but still want something
|
||||||
-----------------------
|
that will work cross-process. It has poor performance, and is only
|
||||||
|
recommended for development or extremely small deployments.
|
||||||
|
|
||||||
Backend Requirements
|
This layer is included with Channels; just set your ``BACKEND`` to
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
``channels.backends.database.DatabaseChannelLayer``, and it will use the
|
||||||
|
default Django database alias to store messages. You can change the alias
|
||||||
|
by setting ``CONFIG`` to ``{'alias': 'aliasname'}``.
|
||||||
|
|
||||||
While the channel backends are pluggable, there's a minimum standard they
|
|
||||||
must meet in terms of the way they perform.
|
|
||||||
|
|
||||||
In particular, a channel backend MUST:
|
In-memory
|
||||||
|
---------
|
||||||
|
|
||||||
* Provide a ``send()`` method which sends a message onto a named channel
|
The in-memory layer is purely an implementation detail used when running
|
||||||
|
the entire Django stack in a single process; the most common case of this
|
||||||
|
is ``runserver``, where a server thread, channel layer, and worker thread all
|
||||||
|
co-exist inside the same python process.
|
||||||
|
|
||||||
* Provide a ``receive_many()`` method which returns an available message on the
|
You should not need to use this process manually, but if you want to,
|
||||||
provided channels, or returns no message either instantly or after a short
|
it's available from ``asgiref.inmemory.ChannelLayer``.
|
||||||
delay (it must not block indefinitely)
|
|
||||||
|
|
||||||
* Provide a ``group_add()`` method which adds a channel to a named group
|
|
||||||
for at least the provided expiry period.
|
|
||||||
|
|
||||||
* Provide a ``group_discard()`` method with removes a channel from a named
|
Writing Custom Channel Layers
|
||||||
group if it was added, and nothing otherwise.
|
-----------------------------
|
||||||
|
|
||||||
* Provide a ``group_members()`` method which returns an iterable of all
|
The interface channel layers present to Django and other software that
|
||||||
channels currently in the group.
|
communicates over them is codified in a specification called :doc:`ASGI <asgi>`.
|
||||||
|
|
||||||
* Preserve the ordering of messages inside a channel
|
|
||||||
|
|
||||||
* Never deliver a message more than once (design for at-most-once delivery)
|
|
||||||
|
|
||||||
* Never block on sending of a message (dropping the message/erroring is preferable to blocking)
|
|
||||||
|
|
||||||
* Be able to store messages of at least 5MB in size
|
|
||||||
|
|
||||||
* Allow for channel and group names of up to 200 printable ASCII characters
|
|
||||||
|
|
||||||
* Expire messages only after the expiry period provided is up (a backend may
|
|
||||||
keep them longer if it wishes, but should expire them at some reasonable
|
|
||||||
point to ensure users do not come to rely on permanent messages)
|
|
||||||
|
|
||||||
In addition, it SHOULD:
|
|
||||||
|
|
||||||
* Provide a ``receive_many_blocking()`` method which is like ``receive_many()``
|
|
||||||
but blocks until a message is available.
|
|
||||||
|
|
||||||
* Provide a ``send_group()`` method which sends a message to every channel
|
|
||||||
in a group.
|
|
||||||
|
|
||||||
* Make ``send_group()`` perform better than ``O(n)``, where ``n`` is the
|
|
||||||
number of members in the group; preferably send the messages to all
|
|
||||||
members in a single call to your backing datastore or protocol.
|
|
||||||
|
|
||||||
* Try and preserve a rough global ordering, so that one busy channel does not
|
|
||||||
drown out an old message in another channel if a worker is listening on both.
|
|
||||||
|
|
||||||
|
Any channel layer that conforms to the :doc:`ASGI spec <asgi>` can be used
|
||||||
|
by Django; just set ``BACKEND`` to the class to instantiate and ``CONFIG`` to
|
||||||
|
a dict of keyword arguments to initialize the class with.
|
||||||
|
|
|
@ -27,7 +27,6 @@ Contents:
|
||||||
getting-started
|
getting-started
|
||||||
deploying
|
deploying
|
||||||
integration-changes
|
integration-changes
|
||||||
message-standards
|
|
||||||
scaling
|
scaling
|
||||||
backends
|
backends
|
||||||
integration-plan
|
integration-plan
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
Message Standards
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some standardised message formats are used for common message types - they
|
|
||||||
are detailed below. Message formats are meant to be generic and offload as
|
|
||||||
much protocol-specific processing to the interface server as is reasonable;
|
|
||||||
thus, they should generally represent things at as high a level as makes sense.
|
|
||||||
|
|
||||||
In addition to the standards outlined below, each message may contain a
|
|
||||||
``reply_channel``, which details where to send responses. Protocols with
|
|
||||||
separate connection and data receiving messages (like WebSockets) will only
|
|
||||||
contain the connection and detailed client information in the first message;
|
|
||||||
use the ``@channel_session`` decorator to persist this data to consumers of
|
|
||||||
the received data (or something else based on ``reply_channel``).
|
|
||||||
|
|
||||||
All messages must be able to be encoded as JSON; channel backends don't
|
|
||||||
necessarily have to use JSON, but we consider it the lowest common denominator
|
|
||||||
for serialisation format compatibility.
|
|
||||||
|
|
||||||
The size limit on messages is 1MB (while channel backends may support larger
|
|
||||||
sizes, all message formats should stay under this limit, which might include
|
|
||||||
multi-part messages where large content must be transferred).
|
|
||||||
|
|
||||||
The length limit on channel names is 200 printable ASCII characters.
|
|
||||||
|
|
||||||
|
|
||||||
HTTP Request
|
|
||||||
------------
|
|
||||||
|
|
||||||
Represents a full-fledged, single HTTP request coming in from a client.
|
|
||||||
|
|
||||||
Standard channel name is ``http.request``.
|
|
||||||
|
|
||||||
Contains the following keys:
|
|
||||||
|
|
||||||
* get: Dict of {key: [value, ...]} of GET variables (keys and values are strings)
|
|
||||||
* post: Dict of {key: [value, ...]} of POST variables (keys and values are strings)
|
|
||||||
* cookies: Dict of cookies as {cookie_name: cookie_value} (names and values are strings)
|
|
||||||
* headers: Dict of {header name: value}. Multiple headers of the same name are concatenated into one value separated by commas.
|
|
||||||
* meta: Dict of HTTP headers and info as defined in the Django Request docs (names and values are strings)
|
|
||||||
* path: String, full path to the requested page, without query string or domain
|
|
||||||
* root_path: Path designated as the "root" of the application (SCRIPT_NAME)
|
|
||||||
* method: String, upper-cased HTTP method
|
|
||||||
* server: [host, port] showing the address the client connected to
|
|
||||||
* client: [host, port] of the remote client
|
|
||||||
|
|
||||||
Should come with an associated ``reply_channel`` which accepts HTTP Responses.
|
|
||||||
|
|
||||||
|
|
||||||
HTTP Response
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Sends either a part of a response or a whole response to a HTTP client - to do
|
|
||||||
streaming responses, several response messages are sent with ``more_content: True``
|
|
||||||
and the final one has the key omitted. Normal, single-shot responses do not
|
|
||||||
need the key at all.
|
|
||||||
|
|
||||||
Due to the 1MB size limit on messages, some larger responses will have to be
|
|
||||||
sent multi-part to stay within the limit.
|
|
||||||
|
|
||||||
Only sent on reply channels.
|
|
||||||
|
|
||||||
Keys that must only be in the first message of a set:
|
|
||||||
|
|
||||||
* content_type: String, mimetype of content
|
|
||||||
* status: Integer, numerical HTTP status code
|
|
||||||
* cookies: List of cookies to set (as encoded cookie strings suitable for headers)
|
|
||||||
* headers: Dictionary of headers (key is header name, value is value, both strings)
|
|
||||||
|
|
||||||
All messages in a set can the following keys:
|
|
||||||
|
|
||||||
* content: String of content to send
|
|
||||||
* more_content: Boolean, signals the interface server should wait for another response chunk to stream.
|
|
||||||
|
|
||||||
|
|
||||||
HTTP Disconnect
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Send when a client disconnects early, before the response has been sent.
|
|
||||||
Only sent by long-polling-capable HTTP interface servers.
|
|
||||||
|
|
||||||
Standard channel name is ``http.disconnect``.
|
|
||||||
|
|
||||||
Contains no keys.
|
|
||||||
|
|
||||||
|
|
||||||
WebSocket Connection
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Sent when a new WebSocket is connected.
|
|
||||||
|
|
||||||
Standard channel name is ``websocket.connect``.
|
|
||||||
|
|
||||||
Contains the same keys as HTTP Request, without the ``POST`` or ``method`` keys.
|
|
||||||
|
|
||||||
|
|
||||||
WebSocket Receive
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Sent when a datagram is received on the WebSocket.
|
|
||||||
|
|
||||||
Standard channel name is ``websocket.receive``.
|
|
||||||
|
|
||||||
Contains the following keys:
|
|
||||||
|
|
||||||
* content: String content of the datagram.
|
|
||||||
* binary: Boolean, saying if the content is binary. If not present or false, content is a UTF8 string.
|
|
||||||
|
|
||||||
|
|
||||||
WebSocket Client Close
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Sent when the WebSocket is closed by either the client or the server.
|
|
||||||
|
|
||||||
Standard channel name is ``websocket.disconnect``.
|
|
||||||
|
|
||||||
Contains no keys.
|
|
||||||
|
|
||||||
|
|
||||||
WebSocket Send/Close
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Sent by a Django consumer to send a message back over the WebSocket to
|
|
||||||
the client or close the client connection. The content is optional if close
|
|
||||||
is set, and close will happen after any content is sent, if some is present.
|
|
||||||
|
|
||||||
Only sent on reply channels.
|
|
||||||
|
|
||||||
Contains the keys:
|
|
||||||
|
|
||||||
* content: String content of the datagram.
|
|
||||||
* binary: If the content is to be interpreted as text or binary.
|
|
||||||
* close: Boolean. If set to True, will close the client connection.
|
|
Loading…
Reference in New Issue
Block a user