http2spdy

HTTP/2 request header compression


Since I'm not an expert, I have a general question concerning HTTP/2.

So as commonly known, HTTP2 compresses headers to reduce the message size. Does this only apply to the response or also to the request? If do a small experiment and run two small HTTP servers, one using version 1.1 and another one using version 2, let both send the exact same content and then request both pages in Firefox, I can see that the response header size is dramatically smaller for the HTTP/2 version. However, the request header size is almost the same. In my understanding this makes sense, because the browser doesn't know in advance, if the server is HTTP/2 capable and therefore can't compress the headers in upfront. Am I right? And if so, is there a way to "enforce" the client to use HTTP/2 (with client I don't mean a brwoser, but a programatic one) and also compress request headers?

And another question: if I wanted to benchmark HTTP/1.1 vs. HTTP/2 performance under load, what would a useful test setup look like, which parameters would be varied and which metrics would it make sense to measure (RTT, TTFB, ...?)


Solution

  • When initiating the connection you negotiate the protocol. The client needs to know if it's talking HTTP/1.1, HTTP/2 or something else before it knows the format to send. For HTTPS connections this is handled by the TLS connection negotiation using ALPN.

    It is also possible to start on HTTP/1.1 for first (or more) requests and then upgrade to HTTP/2 at a later stage. This is handled by the server advertising h2 support over a HTTP/1.1 connection by sending a Upgrade: h2 (for HTTPS) or Upgrade: h2c (for HTTP) HTTP header in the response and then the client can choose to upgrade. This is more useful for HTTP connections where there is no TLS negotiation initially so client would likely assume HTTP/1.1. However all the web browsers have stated they will not support HTTP/2 over HTTP (h2c) and will only support it over HTTPS (h2). I honestly can't think of why a HTTPS connection would start in HTTP/1.1 and then upgrade to HTTP/2 - instead of just starting off as HTTP/2 from the get go, but in theory it is possible.

    You can see an example of the upgrade header by clicking on this link: https://securityheaders.io/?q=https%3A%2F%2Fwww.tunetheweb.com&followRedirects=on Note I'm only using the securityheaders.io website as a quick way to show HTTP headers. In theory you could see the same by going directly to https://www.tunetheweb.com with your browser and look at the response headers but that's very likely to be done over HTTP/2 so won't have the header. Note also that this is an optional header and not all HTTP/2 servers send it (Apache does, NGINX doesn't for example) - probably because it's not that useful over HTTPS as discussed above.

    It is important to understand how the compression works over HTTP/2. For a start you get the benefit of it being a binary rather than text-based protocol so there's some savings there. However the main saving is by avoiding repetition by creating a table of headers. This means the very first request will be the full size and only subsequent requests will be smaller as they replace actual headers with references to the table. And similar for response headers (compression is used for both). Though that's not strictly true as there is a pre-defined, static table of common HTTP headers and values (e.g. GET and /) so there's still some savings in that first request but a lot more on subsequent requests as the longer headers (e.g. user-agents) are replaced by references.

    I'm pretty sure (though not 100%) that browsers show the full size without taking into account HTTP/2 HPACK compression as that's done at a lower level (though most show two figures - both with and without gzip body compression but that's different). To see the actual HTTP/2 details and sizings you'd need to use a tool like Wireshark or Chrome's net-internals page. See this page for some suggested tools: https://community.akamai.com/community/web-performance/blog/2015/06/05/useful-tools-for-http2-debugging. Other point to note is that header size is often tiny compared to most bodies (at least for responses).

    As to performance benchmarking tools that's a massive topic beyond the scope of Stack Overflow as there are so many variables that will affect this (e.g. network location, type - influencing latency and bandwidth - software implementation of HTTP/2 on browser and client side... etc.). Best I can suggest is to replicate your users typical set up as much as possible and repeat tests as much as you can or use RUM (real user monitoring) metrics in analytics software for example. HTTP/2 should make most websites faster but it's not a given. This webpage is a good example of an extremely bandwidth bound site that actually is slower over a HTTP/2 connection without tweaking: https://99designs.ie/tech-blog/blog/2016/07/14/real-world-http-2-400gb-of-images-per-day/

    Hope that helps.