What is HTTP/2 and How to Enable it on Nginx
One of the core technologies powering the web is HTTP. Unfortunately, HTTP/1.1 was designed for static HTML sites and was last updated around 1999. The web today has changed quite a lot. Websites are more and more dynamic and contain a lot of resources. In this tutorial, I will explain what are SPDY and HTTP/2 and how to enable them on Nginx.
Update: SPDY is deprecated now. You don’t need to enable it on Nginx. Instead, you should use HTTP/2.
SPDY
In 2009 Google introduced a new protocol called SPDY (pronounced speedy). SPDY offers three key improvements over HTTP/1.1.
1. Header Compression
Every HTTP request and response includes a sizeable amount of data in the header. There’s a lot of repetitive metadata (user agent and cookies) in the header. HTTP/1.1 can only compress the actual content and can not compress the header. SPDY significantly shrinks the header size. SPDY supports sending header once for an entire connection instead of sending them for every repetitive single connection.
2. Parallel Requests
HTTP is a message-based protocol. Once you have established a TCP connection and you send an HTTP request you have to sit there and wait for the response to arrive before you can send the next request. Each such request requires at least one round trip between the browser and the server which can take hundreds of milliseconds. This is a significant delay. If one of the responses was slow, it will delay all the other requests. This is called head-of-line blocking. Although you can open multiple concurrent connections to send multiple requests at the same time, modern browsers are usually limited to 4~8 concurrent connections per host.
In HTTP, the relationship between the request message and the response message is implicit. The server does not explicitly say I’m the response to that request. You can only identify it’s the response that request because the response follows that request in order.
SPDY offers true multiplexing. With SPDY you can send as many requests as you like at a single connection and get the responses in whatever order. So browsers don’t have to open multiple connections per hostname to send multiple requests. SPDY enables them to open one connection per hostname. This will also reduce the load on the server because fewer connections mean fewer sockets are open on the server.
3. Server Push and Server Hint
In HTTP, all communications between the browser and server are initiated by the browser. If the server has something to say, it actually has to wait for the browser to ask for the information. When the browser request HTML, the server knows the browser needs the associated CSS, JavaScript, or image which needs to be fetched by the browser in order to fully render the page. But in HTTP the server has to wait for the browser to request that css, JavaScript and image.
With SPDY, the server is able to proactively push data without the browser requesting it.
In some cases, server push may be wasteful. For instance, maybe the browser already had the css file in its cache and wouldn’t download it again. SPDY had a lite version of server push called server hint which means the server only offers suggestions to the browser but the request is still made by the client.
The following web performance best practices are no longer needed with SPDY, greatly reducing the developer’s workload.
- CSS Sprite
- Inline Image
- Sharding to improve parallel requests.
- CSS/JavaScript Concatenation
Limitations
SPDY is great but it still has some limitations.
- The first is that it limits to HTTPS.
- SPDY communicates separately with each host. The browser may have to communicates with multiple hosts in order to fully render a webpage. Even if all of them support SPDY, the browser still has to open one connection per host. Multiplexing can only occur on a per host basis.
How to Enable SPDY On Nginx
As said before, you need to enable HTTPS before you can use SPDY. You can easily get a free SSL/TLS certificate from Let’s Encrypt. If you have not yet enabled HTTPS, please use the following tutorial to get a free SSL/TLS certificate.
If you have enabled HTTPS, check if Nginx is compiled with SPDY module
sudo nginx -V
If you see the following text, then SPDY module is included in your Nginx installation.
--with-http_spdy_module
Configure server block file
sudo vi /etc/nginx/conf.d/yourdomain.conf
or
sudo vi /etc/nginx/sites-available/yourdomain.conf
In the server section, add spdy after listen 443 ssl.
server {
listen 443 ssl spdy;
server_name www.linuxbabe.com;
ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/privkey.pem;
......
Then save and close the file. Reload Nginx configuration.
sudo service nginx reload
or
sudo systemctl reload nginx
And you are done. Very easy!
As of Nginx 1.9.5, ngx_http_spdy_module was superseded by ngx_http_v2_module. So if you are using a version higher than 1.9.5, you don’t need to enable SPDY. See the following text to learn HTTP/2 and how to enable it with Nginx.
HTTP/2
HTTP/2 is based on SPDY. The HTTP/2 specification was published as RFC 7540 in May 2015. HTTP/2 has the same semantics as HTTP/1.1. HTTP/2 is binary, instead of textual. HTTP/2 separate response into header frame and data frame.
Improvements over SPDY
HPACK Compression
HPACK is a faster and smarter way to compress header. It’s specifically designed for this work. The ngx_http_spdy_module of Nginx disables header gzip compression by default because it can be attacked by CRIME.
Requires No SSL/TLS
HTTP/2 protocol itself requires no SSL/TLS connection. But the implementation in all major browser vendors Firefox, Chrome, Opera say they will require TLS.
ALPN
With ALPN the browser and the server can establish an HTTP/2 connection from the get-go instead of establishing a HTTP/1.1 connection first and then negotiate an HTTP/2 connection. ALPN is an improvement over NPN which is used by SPDY.
Enable HTTP/2 on Nginx
As of version 1.9.5, Nginx supports HTTP/2, so you have to install a Nginx version at least 1.9.5. I also suggest compiling the latest Nginx with ngx_pagespeed module, but it’s up to you. Use the following link to see how they’re done.
- Install latest version of Nginx on Ubuntu server
- Boost site speed by compiling latest Nginx version with ngx_pagespeed module on Ubuntu server
Like SPDY, it’s really simple to enable HTTP/2 on Nginx. Check if Nginx is compiled with HTTP/2 module
sudo nginx -V
Since your Nginx version is at least 1.9.5, you should see the following text in the output.
--with-http_v2_module
Then configure server block file
sudo vi /etc/nginx/conf.d/yourdomain.conf
or
sudo vi /etc/nginx/sites-available/yourdomain.conf
In the server section, add http2 after listen 443 ssl.
server {
listen 443 ssl http2;
server_name www.linuxbabe.com;
ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/privkey.pem;
......
Then save and close the file. Reload Nginx configuration.
sudo service nginx reload
or
sudo systemctl reload nginx
And you are done. Very easy!
How to Check if HTTP/2 is Working on Your Website
Go to https://tools.keycdn.com/http2-test. And enter your domain. Cloudflare has an excellent post about tools for testing and debugging HTTP/2.
Great!