HTTP/1.1 vs HTTP/2 for backend servers

I was wondering whether HTTP/2 would give meaningful advantages for backend NIO servers, i.e. such which have an nginx or similar proxy in front?

The multiplexing shouldn't have a huge advantage if the connection between the hosts are really fast, maybe even on localhost? (and non-TLS of course)

nginx does not support HTTP/2 on the upstream side when proxying requests.
The rational is that they consider it pointless.

1 Like

Ah cool, so essentially my thinking :slight_smile:

Conceptually there are a few possible advantages, but you're right that in general there is much less pressure to run anything other than HTTP/1 in this case.

1 Like

Care to line out the possible advantages? That the TCP handshake still takes a little longer?

to me, the biggest advantage of HTTP/2 is security, which might also include fraud prevention. for swiftinit, we made the decision some time ago to disable HTTP/1.1 for all unverified IPs, the impact has been uniformly positive, and i can confidently say we are unlikely to ever reenable it.

this however is only relevant for public-facing servers. if you’ve got a proxy in front of it, you should set the proxy to use HTTP/2 only, but it wouldn’t make sense for the server-to-server connections to use HTTP/2, particularly if you don’t have any other components written in swift that are using HTTP/2.

in my mind, when you ignore the security aspects, HTTP/2 is worse than HTTP/1.1 in almost every way. it is harder to use, harder to test, and requires you to fiddle around with TLS for no purpose other than protocol negotiation. you’ve also mentioned that you are trying to limit the amount of source code in your versioning domain, and HTTP/2 would require you to add a dependency on swift-nio-http2. so if i were you i wouldn’t bother with HTTP/2.

1 Like

HTTP/2s main advantage is that it's much cheaper to parse and serialize than HTTP/1. This doesn't apply to all uses of HTTP/2 but does apply to the serialization you'd want to use in this case:

  1. Disable huffman coding for HPACK
  2. Disable dynamically indexed header fields, always encoding the field names/values literally
  3. Set max frame size very large.
  4. Set flow control windows very large.

In this dialect, the data processing is very cheap, cheaper than HTTP/1 which requires often quite-expensive string parsing operations to properly parse.

The other big advantage is that there's fewer files involved. Becasue you can multiplex the backend requests you can run far more requests over fewer FDs. This reduces FD pressure on the machine, which is nice, though hardly a slam dunk win.

To @taylorswift's point, you can also avoid using the TLS piece. HTTP/2 has support for "prior knowledge" flows, which you could use here.

However, this set of tradeoffs has to be balanced with the general use-case, which is supporting as wide a range of backends as possible. In that mode, HTTP/1 is the winner, as it's way more broadly supported.