Silly question, but what's the use case for the HTTP/2 Push? Their example with pushing doesn't make sense to me. Why would you want to push static content?
Silly question, but what's the use case for the HTTP/2 Push? Their example with pushing doesn't make sense to me. Why would you want to push static content?
That being said, I fail to see how in the general case, setting static headers in the server software's config for Push is useful [2][3], and wish that more implementations converged on a common way of describing what to push [4], so that tools could be built around discovering dependencies, and around interpreting that manifest to execute push.
[1] https://docs.google.com/document/d/1K0NykTXBbbbTlv60t5MyJvXj... [2] https://news.ycombinator.com/item?id=14077955#14081237 [3] https://news.ycombinator.com/item?id=12719563#12722383 [4] https://github.com/GoogleChromeLabs/http2-push-manifest
Nginx does have a module [1] and a corresponding configuration option to scan outgoing headers for Link header preload directives, and once it has learned of a preload being declared by a resource, it will push that resource thereafter. Nginx talks about the justification for this feature, where they too admit that statically configuring pushes in the server config is not terribly useful -- it's quite often the wrong place to specify relationships between resources.
[1] https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/
And if you think about it, static pushes in general have very limited usefulness, almost non existent. Imagine when some url becomes popular and almost all of the requests to that url come from people who never visited the website before. It would make sense for a web server to learn what kind of resources clients request with that url and start pushing those resources to people ahead of time.
Similarly, it should be the backend behind the reverse-proxy that knows what's the page that has been just rendered, and knows about the user's session (is it brand new, or maybe it's not new, but still needs to push things because it's too old, and since then that particular page's background changed, etc.).
And in case of an Angular/React/SPA thing, then the "bundler/compiler" should create a list of things to push for various URLs. Or the Angular/React team should talk with the Nginx team to figure out how to speed up things. (In case of SSR - server side rendering - the NodeJS server can emit the necessary Link headers, for example.)
Proxies are already complicated as is. Caching proxies more so. (Think of how Varnish has a - probably Turing complete - DSL to decide what to serve and/or cache and when, and how.)
The HTML parsing approach is probably great from a 80% of the benefit for 20% of the effort on small-scale websites (i.e. majority). A super accurate inference engine might use deep learning to train what to serve on a very personalized level if you have a lot of users & the CPU/latency trade-off makes sense for your business model (i.e. more accuracy for a larger slice of your population). A less accurate one might just collect statistics in a DB & make cheap less accurate guesses from that (or use more "classic ML" like Bayes) if you have a medium amount of users or the CPU usage makes more sense and you're OK with the maintenance burden of a DB. It's a sliding scale IMO of tradeoffs with different approaches making sense depending on your priorities.
That said a simple heuristic like "after requesting an URL the server got these requests on the same HTTP/2 connection in less than 1 second, and those were static assets served with Expires headers" could work.
By "caching layer" he probably meant a proxy or load balancer level cache not the user agent cache. It would make total sense for a load balancer to statistically discover relationships.
Client: GET /index.html
Server: <index.html>
Client (after parsing): GET /main.css
Server: <main.css>
Loading the page thus takes 2 round trips, one for the main page and one for the content. (Or more, if you have e. g. includes in the CSS.) Here's what it would look like with HTTP/2 Push: Client: GET /index.html
Server: <index.html>, <main.css> (PUSH)
This only takes 1 round trip; since the server knows that main.css will be required shortly it can preemptively send it. In particular, this might offer a significant speedup for high-latency connections; it also theoretically reduces the need for bundling tools since you can have the server just push all of the individual files.The obvious problem with this scheme is that if the client already has main.css then it's a waste of bandwidth to send it again. The client can cancel the push, but by the time it finds out about it a bunch of data has already been sent. There is a proposal for 'Cache Digests' which will allow the client to send a Bloom filter of its cache so the server can tell whether or not it has the file already, but as far as I'm aware no major client or server has implemented this yet.
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).
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 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.
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.
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.
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.
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.
- Request index.html
- Parse index.html
- Request .js and .css and .jpg/png, etc found inside
- Parse .js and .css found inside
- Request additional .js, .css and .jpg/png, etc found within js/css
- Parse....
Into this...
- Request index.html, .css, .js, *.jpg/png
- Parse all
To avoid multiple round trips and improve initial page load time if you "know" what's going to be requested from the beginning.
Normally, the browser parses HTML, finds a <link> tag that mentions main.css, and then requests main.css. With HTTP/2 push, by the time the browser has finished parsing the <link> tag, main.css has already been delivered.
If the browser already has main.css in its cache, it can reject the push.
[1]: Yet. I believe the web packaging standard (intended, among other things, to replace AMP) allows pushing bundles signed by other origins.
1. Site and static content are served directly by your webserver. ( HTTP2/push helpful )
2. Site served by your web servers but static content is served by a CDN ( HTTP2/push NOT helpful )
3. Site and static content proxied by some service. ( HTTP2/push helpful )