On Fri, May 6, 2016 at 10:09 AM, Aymeric Augustin < aymeric.augus...@polytechnique.org> wrote:
> Hello Donald, all, > > Some thoughts inline below. > > > On 06 May 2016, at 18:11, Donald Stufft <don...@stufft.io> wrote: > > > > For an example, in traditional HTTP servers where you have an open > connection > > associated with whatever view code you're running whenever the client > > disconnects you're given a few options of what you can do, but the most > common > > option in my experience is that once the connection has been lost the > HTTP > > server cancels the execution of whatever view code it had been running > [1]. > > This allows a single process to serve more by shedding the load of > connections > > that have since been disconnected for some reason, however in ASGI since > > there's no way to remove an item from the queue or cancel it once it has > begun > > to be processed by a worker proccess you lose out on this ability to > shed the > > load of processing a request once it has already been scheduled. > > In theory this effect is possible. However I don't think it will make a > measurable difference in practice. A Python server will usually process > requests quickly and push the response to a reverse-proxy. It should have > finished to process the request by the time it's reasonable to assume the > client has timed-out. > > This would only be a problem when serving extremely large responses in > Python, > which is widely documented as a performance anti-pattern that must be > avoided > at all costs. So if this effect happens, you have far worse problems :-) > I will also point out that I've introduced channel capacity and backpressure into the ASGI spec now (it's in three of the four backends, soon to be in the fourth) to help combat some of this problem, specifically relating to an overload of requests or very slow response readers. > > > > This additional complexity incurred by the message bus also ends up > requiring > > additional complexity layered onto ASGI to try and re-invent some of the > > "natural" features of TCP and/or HTTP (or whatever the underlying > protocol is). > > An example of this would be the ``order`` keyword in the WebSocket spec, > > something that isn't required and just naturally happens whenever you're > > directly connected to a websocket because the ``order`` is just whatever > bytes > > come in off the wire. > > I'm somewhat concerned by this risk. Out-of-order processing of messages > coming from a single connection could cause surprising bugs. This is > likely one > of the big tradeoffs of the async-to-sync conversion channels operates. I > assume it will have to be documented. > > Could someone confirm that this doesn't happen for regular HTTP/1.1 > requests? > I suppose channels encodes each HTTP/1.1 request as a single message. > Yes, it encodes each request as a single main message, and the request body (if large enough) is chunked onto a separate "body" channel for that specific request; since only one reader touches that channel, it will get the messages in-order. It is unfortunate that in-order processing requires a bit more work, but the alternative is having to sticky WebSocket connections to a single worker server, which is not great and kind of defeats the point of having a system like this. I'd also like to point out that if a site has a very complex WebSocket protocol I would likely encourage them to write their own interface server to move some of the more order-sensitive logic closer to the client, and then just have that code generate higher-level events back into Django; Channels is very much a multi-protocol system, not just for WebSockets and HTTP. > > Note that out of order processing is already possible without channels e.g. > due to network latency or high load on a worker. > > The design of channels seems similar to HTTP/2 — a bunch of messages sent > in > either direction with no pretense to synchronize communications. This is a > scary model but I guess we'll have to live with it anyway... > Yes, it's pretty similar to HTTP/2, which is not entirely a mistake. If you're going to take the step and separate the processes out, I think this model is the most reasonable one to take. > > Does anyone know if HTTP/2 allows sending responses out of order? This > would > make sub-optimal handling of HTTP/1.1 pipelining less of a concern going > forwards. We could live with a less efficient implementation. > It does; you can send responses in any order you like as long as you already got the request matching it. You can also push other requests _to the client_ with their own premade responses before you send a main response (Server Push). > > > > I believe the introduction of a message bus here makes things inherently > more > > fragile. In order to reasonable serve web sockets you're now talking > about a > > total of 3 different processes that need to be run (Daphne, Redis, and > Django) > > each that will exhibit it's own failure conditions and introduces > additional > > points of failure. Now this in itself isn't the worst thing because > that's > > often times unavoidable anytime you scale beyond a single process, but > ASGI > > adds that complication much sooner than more traditional solutions do. > > Yes, that’s my biggest concern with channels. However I haven’t seen anyone > suggesting fewer than three systems: > > - frontend + queue + worker (e.g. channels) > - regular HTTP + websockets + pub/sub (e.g. what Mark Lavin described) > > I share Mark’s concerns about handling short- and long-lived connections in > the same process. Channels solves this elegantly by converting long-lived > connections to a series of events to handle. > I'm also working on an IPC-based channel layer (currently at https://github.com/andrewgodwin/asgi_ipc) that will let you drop one moving part provided you can host everything on one machine. This might me more suited to those who want to run small clusters of interface and worker servers with HAProxy balancing over them, which I think is how I might want to run things. > > This sounds a lot like the proof-of-concept I demonstrated at DjangoCon US > 2013, eventually reaching the conclusion that this wasn't a workable model, > mainly due to: > > - the impossibility of mixing async and sync code in Python, because of the > explicit nature of async code written on top of asyncio (which I still > believe is the right choice even though it's a problem for Django). > > - the great difficulty of implementing the ORM's APIs on top of an async > solution (although I came up with new ideas since then; also Amber Brown > showed an interesting proof-of-concept on top of Twisted at Django under > the Hood 2015). > > I think it's important to keep a straightforward WSGI backend in case we > crack > this problem and build an async story that depends on asyncio after > dropping > support for Python 2. > I agree, and I would love to see more native async code as we go forward that interoperates with both async webservers and async channel worker classes. There is not yet a standard for "async WSGI", and I suspect ASGI can at least partially fulfill this role with the message formats (which are an improvement on the WSGI environ() for HTTP as things like encoding are fully defined, and also provide a WebSocket format that doesn't exist), if not by using something very close to the current API; after all, it's basically just an eventing API. > I don't think merging channels as it currently stands hinders this > possibility > in any way, on the contrary. The more Django is used for serving HTTP/2 and > websockets, the more we can learn. > > > Sorry Andrew, that was yet another novel to read… I hope it helps anyway… > No, thanks Aymeric, this was great to read. The more feedback the better. Andrew -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To post to this group, send email to django-developers@googlegroups.com. Visit this group at https://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CAFwN1upSazQiOCKgoH%2BFEwtYbxeUOh878MXrHZCfPsAZ4J6L0Q%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.