Subject: unclaimed push streams using up the connection window

From: William Chan (陈智昌) <[email-masked]>
Date: Mon, 19 May 2014 16:26:00 -0700

https://groups.google.com/d/msg/spdy-dev/hz9jp2rZbdQ/33bSPcbNWwwJ has the
full discussion on spdy-dev@.

The short of it is that it's possible for unclaimed push streams to use up
all of the connection window and stall all other streams. This might be due
to a server bug where it is "leaking" the push streams by associating them
to a stream that will never generate requests for the pushed URL. In the
example case, the document simply says "hello world", but it has associated
push streams. Since this document will never generate requests for those
push streams, they are essentially leaked. Furthermore, when the browser
reloads the page, the push streams aren't killed off, so they still suck up
all the connection window which never reopens since nothing is claiming the
stream. So the hello world page hangs on reload.

There are implementation and protocol mitigations here:
1) A browser implementation could track all the associated push streams for
a page and kill them when the page goes away. That's pretty ugly and
violates some layering boundaries between the network stack and the web
rendering engine.
2) If the client push implementation streams the push streams directly into
cache, and manages the cached resources with a cache eviction policy, then
the push streams will not persistently suck up the connection window, since
they will get drained as fast as the cache can consume them.
3) From a protocol standpoint, we could separate push and pull connection
windows so they can be managed separately.

In Chromium's case, I think this will be a non-issue when we change our
push implementation to stream directly to cache. I think this is only an
issue if you have an HTTP/2 implementation that chooses to enable flow
control yet has a naive push implementation.

Originally, I thought this was more interesting to ietf-http-wg@, but maybe
this isn't and implementations will figure it out. I'm not sure if there's
anything for the working group to do here. But I'll send this email out
anyway in case others feel differently.

Cheers.

---

From: David Krauss <[email-masked]>
Date: Tue, 20 May 2014 11:07:27 +0800

On 2014–05–20, at 7:26 AM, William Chan (陈智昌) <[email-masked]> wrote:

> 1) A browser implementation could track all the associated push streams for a page and kill them when the page goes away. That's pretty ugly and violates some layering boundaries between the network stack and the web rendering engine.
> 2) If the client push implementation streams the push streams directly into cache, and manages the cached resources with a cache eviction policy, then the push streams will not persistently suck up the connection window, since they will get drained as fast as the cache can consume them.
> 3) From a protocol standpoint, we could separate push and pull connection windows so they can be managed separately.

Isn’t separation of windows (connection vs. stream) already a network layering violation? Why fragment flow control further? Pull streams are more critical but there’s still a bug if pushes are blocked.

Extending the connection window separately from a stream window simply indicates broken design. Is there any use-case that has been proven reliably interoperable? Why the commitment to this setup, given the problems a la BLOCKED?

If the client has nowhere to put the data at the time it’s pushed, then toss it in the bit-bucket and terminate the stream immediately. Delaying a PUSH until it’s useful defeats the purpose of pushing. It sounds like the described application model needs a per-page push cache, if the global cache won’t do. Trying to let the data to collect indefinitely on the server side can’t be good for anyone.

If it’s a performance issue, then send a PRIORITY frame instead.

> In Chromium's case, I think this will be a non-issue when we change our push implementation to stream directly to cache. I think this is only an issue if you have an HTTP/2 implementation that chooses to enable flow control yet has a naive push implementation.

Flow control is not optional. Push is. How is streaming directly to the cache not the naive implementation? More specialized protocols (which may not have a cache but wish to push, for example, firmware updates) should reject unwanted pushes as a rule, I would think.

> Originally, I thought this was more interesting to ietf-http-wg@, but maybe this isn't and implementations will figure it out. I'm not sure if there's anything for the working group to do here. But I'll send this email out anyway in case others feel differently.

Thanks, it’s good to have a handle on what implementation issues are driving evolution. Perhaps there should be another list for implementation discussion?