Last year marked a milestone in the world of Internet technology: the confirmation and standardization of HTTP/2. Popular web servers like Apache and Nginx already support HTTP/2, as do the latest versions of most browsers.
Data shows that by the middle of 2015, very few web sites and services had switched to HTTP/2, only 0.4%. The latest statistics (September 2016) show a significant increase: from 0.4 to 10%. It wouldn’t be that wild a prediction to say more and more sites are going to be making the switch and at a faster rate.
Now’s as good a time as any to start thinking about the practical aspects of switching to HTTP/2, and this is what we’ll be covering in today’s article. We’re particularly interested in looking at how existing web-site optimization methods can be adapted for the new protocol.
Before we start, let’s look at the history of HTTP/2 and see what sets it apart from HTTP/1.1.
From HTTP to HTTP/2
A Brief History
The first description of HTTP (HyperText Transfer Protocol) was published in 1991. Version 1.1 was developed in 1999 and has been in use ever since. At that time (over 20 years ago), websites were far from what they are today. In a relatively short period, sites got much “heavier”; statistically speaking, the average web page today contains roughly 1.9 MB of data, including images, JS and CSS files, etc.
Due to limits on the number of permitted simultaneous HTTP/1.1 connections, pages with lots of heavy content load at a snail’s pace. There are two possible solutions to this problem. The first involves various optimization techniques (some of which we’ve already written about); the second involves modifying the actual protocol to get rid of any bottlenecks. Let’s take a closer look at these two options.
The first major attempt to reform HTTP was made by Google engineers in 2009. This was the SPDY protocol. The goal was to speed up websites and applications by modifying the traditional methods of sending and receiving requests.
Since SPDY requires both server-side and client-side support, Google’s developers came up with special modules for Apache (mod_spdy) and Nginx (ngx_http_spdy_mdoule). Almost all major browsers today support SPDY.
HTTP/2, which was introduced six years later, is in a lot of ways based on SPDY. The new HTTP version was created by the Hypertext Transfer Protocol Working Group. In May 2015, the HTTP/2 specifications were published under RFC_7540.
HTTP/2 is backwards compatible with HTTP/1.1. The changes made to remove bottlenecks and increase performance are in a lot of ways an extension of SPDY. We’ll take a brief look at the most significant ones.
HTTP/2: Main Updates
This is possibly the biggest advantage of HTTP/2. In HTTP/1.1, each request requires a separate TCP connection. Multiplexing lets browsers make multiple requests over one TCP connection:
Modern browsers can only establish a limited number of simultaneous TCP connections. This is why pages with lots of static content don’t load as quickly as we’d like.
Thanks to multiplexing, static elements in HTTP/2 download in parallel, which significantly improves performance.
The ability to prioritize is another innovation in HTTP/2. Now, every request can be assigned a priority. There are two ways priority is assigned: based on weight or based on dependencies.
In the first approach, every stream is assigned a weight. Based on this weight, the server distributes loads among streams. We see this method in SPDY.
The second and primary approach of HTTP/2 involves the browser first requesting the server to return specific content based on type; for example, the browser might first request CSS or JS files, then the HTML, and then images.
In HTTP/2, prioritizing is not necessary, but it is preferred as multiplexing won’t work as it should otherwise. Downloads might even be slower than in HTTP/1.1. Resources with lower priorities will monopolize bandwidth, thus lowering performance.
HTTP Header Compression
Web pages today consist of many different elements: images, JS, CSS, and so forth. Every time the browser requests one of these elements, it also sends an HTTP header. The server also adds a header to requested elements. This consumes major resources.
In HTTP/2, headers are compressed. This decreases the amount of information exchanged between the server and browser. Instead of gzip/deflate algorithms, HPACK is used. This decreases BREACH attack vulnerability.
HTTP/2 and Security
One of the most important requirements of SPDY is that all client-server connections must be encrypted (HTTPS). HTTP/2 does not have this requirement; however, browser developers have decided to introduce the new protocol only for TLS (HTTPS) connections. So, anyone thinking about switching to HTTP/2 first has to make the switch to HTTPS.
This isn’t only necessary for HTTP/2; connection security is one of Google’s ranking factors. Browsers (see here and here) will soon flag sites that don’t support HTTPS as “unsafe”. Also, many HTML5 functions, like geolocation, won’t be available without a secure connection.
Basic HTTP/2 Configurations for Nginx and Apache
Below are basic connection and configuration instructions for Nginx and Apache. As we’ve already said, most browsers now will only work with HTTP/2 over TLS, which is why web servers have to be properly configured.
HTTP/2 is only supported in the latest versions of Nginx (1.9.5 and above). If you currently use an earlier version, you will have to update.
Open the configuration file /etc/nginx/nginx.conf and in the server section, find the following line:
listen 443 ssl;
and replace it with
listen 443 ssl http2;
Save these changes and restart Nginx:
$ sudo service nginx reload
Apache only supports HTTP/2 in versions 2.4.17 and up. If you have an earlier version installed, update and install the mod_http2 module. Then, add the following lines to the configuration file:
# for an https server Protocols h2 http/1.1 # for an http server Protocols h2c http/1.1
Afterwards, restart Apache and you’re done. This is all you need for a simple configuration.
HTTP/2 and Site Optimization
HTTP/2 is backwards compatible with HTTP/1.1, so in principle, you don’t really have to do anything: there is no threat to the operation of your service.
However, as other popular web services and browsers make the switch to HTTP/2, you’ll notice that your site, which was once optimized to improve load times and performance, isn’t working as quickly as it had before.
A lot of the optimization methods which were successful in HTTP/1.1 won’t be in HTTP/2. Some just need to be modified, but others won’t work at all. Let’s take a closer look at these.
Combining Imagines in Sprites
In HTTP/1.1, it was more convenient to download one large image than send multiple requests and download a lot of smaller ones. This was because requests were queued behind one another. The most common way to speed up load times was to combine multiple smaller images in a sprite file.
Sprites are returned for single requests. Even if a user opened a page that had only one small image, the entire sprite would have to be loaded.
Thanks to multiplexing, HTTP/2 doesn’t have this problem; however, sprites may still be useful in some scenarios. Bringing several images together in a sprite (especially if these images are all on the same page) helps improve compression and thus decreases the amount of data that has to be downloaded.
Embedding Images with DataURI
Another popular solution to the multiple HTTP request issue in HTTP/1.1 is embedding images using DataURI. This significantly increases the size of style tables.
If you use embedded images and also concatenate JS and CSS files, users will most likely have to download all of the corresponding code, even if they don’t visit pages with these images.
In HTTP/2, it’s likely that this will worsen performance instead of improving it.
JS and CSS Concatenation
CSS and JS files are often concatenated to optimize websites. This combines various small files into a single larger file. This is an effective workaround for the limited number of simultaneous HTTP requests.
Concatenation may lead to the same problem we see when using sprites: when a user opens a single web page, they immediately download all of the site’s CSS and JS files (most of which are unnecessary). Of course, we could pick out the files for each individual page, but that would take an inordinate amount of time.
Another issue is that all of the concatenated file’s elements need to be simultaneously cleared from the cache. It’d be impossible to set one expiration date for some elements and another for the rest (which are used a lot more often). If we change even a single line of CSS, all of the elements will immediately expire.
Is it worth implementing concatenation in HTTP/2? If HTTP requests don’t consume significant resources, then we can completely avoid it. Downloading multiple smaller style files doesn’t create any problems. There also won’t be any issues with caching or expiration dates.
HTTP/1.1 limits the possible number of simultaneous connections. To get around this limit, you have to load static resources from one domain’s multiple subdomains. This method is called domain sharding, and it’s often used for image-heavy pages. This helps increase load speeds, but creates additional problems.
The need for domain sharding dissolves when you switch to HTTP/2, where you can request as many resources as you need. Moreover, in the case of HTTP/2, sharding doesn’t increase performance, but reduces it since it creates additional TCP connections and interferes with priorities.
When to Make the Switch
When should you plan on switching to HTTP/2? There’s no real single answer to this. We will however share this tip with you: regularly review you service’s visitor logs. When you see that the majority of visitors are using HTTP/2 supported browsers, it’s time to switch. HTTP/2 is presently supported in Chrome (desktop and mobile), Firefox, Opera, Edge, and Safari.
When planning the switch, it’s worth keeping in mind your project’s specifications. If a lot of your visitors access your page from mobile devices, then you’d be better off switching to HTTP/2 sooner. The protocol’s advantages will be much more obvious on smartphones and tablets. However, there are still some thing to consider; for example, Opera Mini is used in many parts the world, but this browser still doesn’t doesn’t support HTTP/2.
If you’re planning on launching a new web service, keep the future transfer to HTTP/2 in mind. Of course, you’ll still have to use HTTP/1.1 for a while, but can already start implementing optimization methods to make life easier in the future.
For our conclusion, we’ll leave you with some links you may find interesting:
- http://httpwg.org/specs/rfc7540.html — HTTP/2 complete specifications
- https://http2.github.io/faq/ — HTTP/2 FAQ, a brief but informative extract from the above link
- https://daniel.haxx.se/http2/ — HTTP/2 Explained, written by Daniel Stenberg, the developer behind curl
- A presentation on optimizing sites for HTTP/2