This is HTTP
A big friendly unsecured clear-text, line-oriented bear.
This is SPDY
A multi-plexed binary TLS-wrapped protocol from the future.
SPDY (pronounced speedy) is a replacement for HTTP, and feels like a wrapper for it. SPDY is a packet (frame) oriented binary protocol, usually wrapped in TLS (SSL), and as such a little harder to follow than HTTP. Our care free days in the jungle, surviving on the bare necessities and debugging connections with telnet, are coming to an end. In exchange, we get faster loading apps, which are secure by default.
The most important goal of SPDY is to transport web content using fewer TCP connections. It does this by multiplexing large numbers of transactions onto one TLS connection.
- From: http://hacks.mozilla.org/2012/02/spdy-brings-responsive-and-scalable-transport-to-firefox-11/
SPDY should require no changes to a web application, in the same way that you can usually ignore whether your app is being accessed over HTTPS or HTTP. Only the web browser and web server need to know. However, if you’re ever used something like telnet or wireshark to debug your site, you’ll want to understand SPDY.
The SPDY equivalent of an HTTP request / response is a stream. Each stream has an unique id, and handles a single request /response.
A stream is split into frames. A control frame contains the HTTP headers. A data frame contains the data. In a response the data might be an image or gzipped HTML. If the request has data frames, they usually contain POST data. The response data can be split over several interleaved data frames.
Where HTTP was connection-oriented, SPDY feels packet oriented. Add the binary structure, and SPDY feels more like TCP than HTTP, even though it preserves HTTP’s semantics.
SPDY in action
The easiest way to see SPDY in action is with Google Chrome / Chromium. Browse to “chrome://net-internals”:chrome://net-internals in one tab, and to https://www.google.com in another. Click SPDY in the sidebar, click a session, then click SPDY_SESSION (you’re in Events now).
1. The request starts with a
SYN_STREAM frame, containing the HTTP request, including the headers.
2. The server replies with a
SYN_REPLY frame, containing the HTTP response headers.
3. Then the server sends one or more
DATA frames, containing whatever the server requested (e.g. index.html).
The headers in a control frame are zlib compressed, although Chrome is kind enough to hide that. SPDY headers are mostly the same as HTTP – see HTTP layering over SPDY for differences.
By default the browser doesn’t show if you’re using SPDY; the address bar shows https (which is technically a lie). Chrome and Firefox have extensions which put a green thunderbolt in the address bar if you’re using SPDY:
Another option for exploring SPDY connection is
spdycat, part of spdylay. To build, this requires OpenSSL>=1.0.1, which for Ubuntu means 12.04+. Once you have it built run:
spdycat -nv https://www.google.com
HTTP vs SPDY example
If your webapp needs 10 images:
- The browser opens 6 TCP connections to the server, and request an image in each.
- It waits on each of those connections for an answer from the server.
- Then it requests the next four.
- The browser opens a single TCP connection, and sends 10
SYN_STREAMrequests down it, opening one stream for each image.
- The server sends 10
SYN_REPLYresponses, one for each stream (image). It can start sending
SYN_REPLYafter the first
SYN_STREAMis received, it does not wait for the client to finish.
- The server sends 10 or more
DATAframes. The data for each image will take at least one
DATAframe, but may be be split over any number. Each
DATAframe has the id of the stream (request) it belongs to. The
DATAframes for the images can be interleaved. The content of a
DATAframe can always be gzipped, even if the client doesn’t advertise support; gzip is required by the protocol.
- The client can send more
SYN_STREAMframes (open more requests) whilst it is receiving data for previous requests. The communication is asynchronous.
By reusing a single TCP connection, SPDY plays better with TCP’s congestion window management, and avoids the slow start problem.
Wrapped in TLS
You initiate a SPDY connection by browsing to an HTTPS site, on port 443. SPDY could have used a different port (it is a different protocol), but because of the risk of that port being firewalled, port 443 was re-used. During the TLS handshake (specifically ClientHello and ServerHello) TLS extension Next Protocol Negotiation (NPN) is used for the server to advertise a list of protocols it supports. As of now www.google.com is sending
spdy/3 spdy/2 http/1.1. The client chooses which to use.
spdy protocol is selected, TLS transports SPDY. If
http/1.1 was chosen, TLS transports HTTP, as it does for regular https sites. If a client does not advertise that is supports NPN the server should assume an http/1.1 connection.
The network layers look like this: TCP ( TLS ( SPDY ( HTTP ) ) ). TCP transports TLS, which carries SPDY, which feels like it wraps HTTP.
One of the most exciting parts of SPDY is server push. The term can be confusing: It is not intended for push in the web sockets / server-sent events / comet sense. Instead it allows the server to send data (typically media) to the client without the client asking.
When a client requests, say, index.html, the server can open it’s own streams (by sending a
SYN_STREAM to the client), and send all the media the client will need, before it sends the contents of index.html. By the time the client parses the html, it will already have all the media in it’s cache. The hope is that this reduces or eliminiates the need for spriting images, packing assets, etc.
The server can only send associated streams whilst the original stream is open. I think of them as sub-streams.
I have not seen server push being used anywhere yet, and neither Firefox nor nginx support it. If you know of a site using server push, please post in the comments!
SPDY is supported in Chrome, in Firefox since version 13, and in Android’s browser. See caniuse.com/spdy for updates since this was written.
Many google properties are SPDY enabled: https://www.google.com, https://gmail.com, etc. The other major site supporting SPDY is twitter.
The following servers have some form of SPDY support:
- Apache with mod_spdy
- Nginx if you apply the spdy patch
- Jetty, a Java servlet container.
- Netty, a Java network application framework.
- Node.js with node-spdy
mod_spdy is very easy to setup. Once you have https working in Apache, just follow the two line instructions here: mod_spdy installation.
What can we do now
The best way to prepare for SPDY is to switch your site to HTTPS only. SPDY only exists inside a TLS (SSL) connection.
If you’re brave, two options for using SPDY today are:
- Front your app with a SPDY-to-HTTP reverse proxy. That should give you most of the benefits of SPDY without any change to your backend.
- Serve static media from a SPDY-enabled server. Static media is usually the bulk of the requests on a webapp, so it would benefit the most.
Any of the servers in the Support section above should work here. You could also try Spdyd (static file server) and Shrpx (SPDY -> HTTPS reverse proxy) from spdylay. To build spdylay you’ll need OpenSSL 1.0.1 or later, which on Ubuntu means 12.04+.
The risk-averse option is to wait until the nginx spdy patch is merged, and just upgrade your nginx.
- The SPDY Book by Chris Strom provides a thorough and enjoyable coverage of SPDY.
- The specification, obviously, but it’s actually quite readable.
- Firefox’s announcement post provides a good introduction.