Hacker News new | ask | show | jobs
by cedricziel 2982 days ago
I think there's a common misconception with the term "push". HTTP2 doesn't push in terms of a push notification, but rather "pushes" assets down the connection that are known to be needed by the currently transferred document (whatever that may be).

That way, the web server can pro-actively push the named stylesheet to the client as it knows that the stylesheet is needed to render the page. That way the client doesn't have to ask the server (which would result in a new roundtrip).

2 comments

"that are known to be needed by the currently transferred document"

How does the server knows what the browser/client "needs" ? The client can have the cached stylesheet already. Making the server "in control" seems wrong and make things even more complicated.

That's the thing, it doesn't. HTTP2 Push is one of the big "open field" of HTTP2, and to know whether a document needs to be pushed will rely on good heuristics and black magic.

There is however a small standard that's emerging, pioneered by h2o, called casper (https://h2o.examp1e.net/configure/http2_directives.html#http...). The idea is that all resources ever sent to the client are stored in a probabilistic data structure in a cookie. On every request the structure is sent back to the server, which can then check whether the resource has good chances to be already known by the browser.

By the way there are some benchmarks done by h2o's author here: http://blog.kazuhooku.com/2015/10/performance-of-http2-push-.... The conclusion is all yours.

The client can cancel the push. But yes, there's definitely wasted bandwidth here - the reason to still do it is that connections are now fast enough that the extra download time is small compared to the time required to parse HTML/send new HTTP request/receive response/render CSS.
That's a very Silicon Valley way to look at things. How much does that bandwidth cost on dial-up or 2G?
The client will kill the connection if it has the file cached, sooooo, not much.
I'm more concerned with a more "traditional" setup - say a festival providing WiFi to many people through limited upstream. Used to be, you could provide a caching proxy locally.

With the war on mitm, it's really hard to set up something that scales traffic in this way - even if the actual data requested by clients could readily scale.

I know it's a trade-off between security and features - but it still makes me sad.

It's 2G. By the time the cancel is received by the server, the server will have sent the resource, the bytes will have traveled and the user will be billed.
First you get a PUSH_PROMISE request that is a single frame. It's tiny.

That tells the client what the server wants to send.

The client can respond with a an RST_STREAM frame https://http2.github.io/http2-spec/#RST_STREAM Again, that's a single frame.

By design it's meant to be extremely small and quick even on high latency, and/or low bandwidth connections.

The client can disable push, so if it's on 2G, it can avoid this issue entirely.
A copy of the spec can be found here:

https://http2.github.io/http2-spec/#PushResources

There's a few interesting things here that I want to point out: * "A client can request that server push be disabled" This is part an explicit parameter in the client request to a server for anything, https://http2.github.io/http2-spec/#SETTINGS_ENABLE_PUSH.

* "Pushed responses that are cacheable (see [RFC7234], Section 3) can be stored by the client, if it implements an HTTP cache. Pushed responses are considered successfully validated on the origin server (e.g., if the "no-cache" cache response directive is present ([RFC7234], Section 5.2.2)) while the stream identified by the promised stream ID is still open"

Note that pushed content first starts with a PUSH_PROMISE message to the client, which the client can decide on its own volition to reject. Note the spec for a PUSH_PROMISE frame is here, https://http2.github.io/http2-spec/#PUSH_PROMISE and it's extremely small. Even on 2G or dial-up it's by design negligible.

* "Once a client receives a PUSH_PROMISE frame and chooses to accept the pushed response, the client SHOULD NOT issue any requests for the promised response until after the promised stream has closed.

If the client determines, for any reason, that it does not wish to receive the pushed response from the server or if the server takes too long to begin sending the promised response, the client can send a RST_STREAM frame, using either the CANCEL or REFUSED_STREAM code and referencing the pushed stream's identifier. "

Wittingly or otherwise, your message comes across as "everyone on the standards boards are idiots, don't think about anything beyond the valley, and I'm smarter than they are." That's beyond ridiculous. The standard was designed by subject matter experts from right across the world, with interests in web technologies across all sorts of markets, including the developing nations where every single byte is important. There's a lot that has been designed in to the HTTP 2.0 specification to account for that and to explicitly try to improve end user experience under those conditions.

The server doesn't send the data every time. First it sends a data frame letting the client know "hey, I've got this thing if you need it" and the browser can respond with a frame saying "nah, don't need it".
The main problem with http2 push and why it’s pointless is that it’s not cache aware.

So you’re pushing unrequested data to everyone regardless.

h2o tries to solve this problem with a special cookie. More here:

http://blog.kazuhooku.com/2015/12/optimizing-performance-of-...

But without something like that it’s a feature that will never really gain traction.

The danger here is that you push too much, but the actual response will still be delivered almost as fast (due to non-blocking behavior in HTTP/2 connections), so sure, it's not optimal, but there are a lot of use cases besides static assets where it is very useful.