mod_h[ttp]2

HTTP/2 for Apache httpd

Earlier

There is one more thing I managed to get into the upcoming Apache httpd 2.4.24: earlier PUSHes.

The table below shows how long it took for a HTTP/2 client (nghttp) to see response and associated PUSHed resources. Time is given in seconds since connection start, so this includes all TLS handshakes and such. Client and server running on the same machine.

RequestDirectivePromises103 StatusPromised ResponseMain Response
Local FileHeader add 0.013 - 0.0130.013
H2PushResource0.0130.0130.0130.013
Proxy FileHeader add 0.024 - 0.0250.024
H2PushResource0.0130.0130.0130.024
Local CGIHeader add 0.091 - 0.0910.091
H2PushResource0.0130.0130.0130.091

The red numbers are from Apache 2.4.23 and older, the green ones are from 2.4.24. As you can see, PUSHes can now happen much earlier and reach the client faster than before.

There are three variations of a resource setup listed, all of which are configured to PUSH 2 local file resources. The main, requested resource is a:

  1. Local File: serving a local HTML file. Here no difference in methods can be seen. It all happens so fast.
  2. Proxy File: using mod_proxy> to server a file from another local server. This example is from a warmed-up proxy connction. But still the new PUSHes happen 11 ms earlier.
  3. Local CGI: serving a simple Python script via mod_cgid. This is a simple CGI setup without any optimizations. Here you can see improvements of 78 ms.
Of course the exact improvements depend on your setup and hardware and several other things involved. Numbers are just from my development laptop without any special tweaking.

What causes this difference?

There are now two different methods to PUSH resources now in Apache httpd 2.4.24:

  1. Header add: which uses mod_headers to add Link: headers to a response which then triggers mod_http2 to perform PUSHes.
  2. H2PushResource: a new directive in 2.4.24 (or mod-h2 v1.8.0) that triggers when a request is read and performs PUSHes and generates Link: headers as needed.
The problem with the first approach is that it needs to wait for the real response. And that takes time to compute. The second one can PUSH when a request has been parsed (and certain things like authentication and permission check have happened). And this often is significantly earlier.

The idea for this comes from Tatsuhiro Tsujikawa, maker of nghttp2 and is proposed by Kazohu Oku, the person behind he h2o server, as a new standard. They both thought about how to improve on the Link header response and Tatsuhiro came up with the idea of using an interim response. The draft describing this has been submitted to the HTTP working group.

103, being in the 1xx status range, is an interim response, meaning it precedes the real response which is yet to come. The HTTP standard talks about it here. You might be familiar with the 100 status code that is often used when uploading data to a server. But a client may receive many 1xx resposnes before the real one and is expected to parse them and ignore them if they mean nothing to it. That is what the standard says.

But implementations do not always follow the standards and also mod_http2 was guilty of not respecting this aspect correctly. No more! 1xx responses, generated by the application, are forwarded to the client on HTTP/2 connections. And not only forwarded, but if such a response carries Link headers, the can trigger PUSHes just as the final response does.

For using Apache as a reverse proxy, this currently means:

As usual, you can also throw this into your 2.4.23 Apache with v1.8.0 from github.

Münster, 17.11.2016,

Stefan Eissing, greenbytes GmbH

Copyright (C) 2016 greenbytes GmbH

Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. See LICENSE for details.