Wednesday, 9 March 2016
Sometimes, a Web site needs to send a client to another server; for example, when it becomes overloaded, entering a maintenance window or it thinks another server might be closer or otherwise better for that user.
One common way to do this is to use DNS for “global load balancing”; by assigning short lifetimes to query responses, the site can shift traffic around to different servers depending on things like load, availability and client location.
DNS-based load balancing relies upon the client opening new connections relatively often, to give the load balancer an opportunity to reassign the client to a new server. It works especially well with HTTP/1.1, because even with persistent connections, browsers tend to cycle through connections pretty quickly.
However, HTTP/2 is designed to have one long-lived connection between the browser and the server. This has great benefits for performance and network utilisation, but interferes with global load balancing; it makes traffic “stickier.”
We needed a better way to shift traffic around for HTTP/2.
What are Alternative Services?
Alternative Services allow a Web server (technically, an Origin – the thing identified by the scheme, hostname, port tuple) to say that another server is authoritative for its resources. Clients that support Alternative Services can open a connection and treat the alternative service as if it were the origin.
Importantly, this is optional; the client isn’t required to use the alternative, and while it’s opening up the alternative connection, it can still use the origin connection. That means that from the end users’ standpoint, there aren’t any hiccups or pauses when the server is switched over.
Just as importantly, using an alternative service doesn’t change the URL in the location bar,
document.location or any other indication of where the resource is; this is a “layer below” the URL.
Alternative services can redirect clients to other alternatives, and instruct clients to cache the association for a period of time. This gives the flexibility of DNS-based global load balancing without the downsides; many people have called it DNS CNAMEs inside of HTTP.
At the same time, an alternative service can be used to upgrade the underlying protocol; for example, from HTTP/1.1 to HTTP/2.
A server can inform clients about an an alternative with a HTTP response header:
HTTP/1.1 200 OK Content-Type: text/html Cache-Control: max-age=600 Alt-Svc: h2="new.example.org:443"; ma=600 ...
This tells the client that for the next ten minutes, it can connect to
new.example.org on port 443 using HTTP/2 and consider it the same server as the origin.
If the connection is using HTTP/2, there is also an
ALTSVC frame type that the server can send to clients to convey the same information. Because it’s a frame, it doesn’t have to be attached to a particular response, meaning that the server can redirect clients before they make any requests, or when they’re idle.
The ability to redirect clients to use another server in a transparent, persistent fashion brings some obvious security concerns.
So, to use an alternative, a client needs to have what we call “reasonable assurances” that it has the authority to do so. In this specification, we define one way to do that; the alternative needs to present a TLS certificate that’s valid for the origin – not the alternative! – hostname.
Other browsers haven’t committed to supporting it yet. Hopefully we’ll hear something from them soon, so servers can stop abusing DNS to shift load around.