Setting up HTTP/2 for Nginx
In Racing Trim
Since its beginnings, the World Wide Web has primarily been based on two technologies: the Hypertext Markup Language (HTML) and the Hypertext Transfer Protocol (HTTP). HTML is by far the better known technology and the one with the more turbulent past. In addition to questionable technological overkill (e.g., the <blink>
tag), conflicts between implementers have been a constant sideshow to the language's evolution. Some further developments such as XHTML have proved to be a technological dead end, causing considerable additional work in quite a few projects.
HTTP/2 at a Glance
Compared with HTML, however, the further development of HTTP has taken place rather covertly and has not been determined by political motives or marketing measures to any great extent. As it has become clear that many websites need to be available 24/7 and that failures could quickly become very expensive – not just in the e-commerce sector – the focus has shifted to solid technology and extensive compatibility. Innovations are therefore slow to catch on and have undergone intensive testing.
Today, only about half of all websites support HTTP/2 [1], even though it was standardized in RFC 7540 [2] back in May 2015. In the case of the Nginx web server, the ngx_http_v2_module
module replaced its predecessor ngx_http_spdy_module
in September 2015 (Nginx 1.9.5). April 2016 saw the module enter the stable branch (Nginx 1.10.0) [3]. By the way, the development of the Nginx module was financed by Dropbox and Automattic (WordPress).
The big websites in particular were early adopters of HTTP/2, preferring it over HTTP/1.1. For them, features like superior compression or request multiplexing were attractive because they directly improved the user experience thanks to higher speed. Today, HTTP/2 for websites is no longer a unique selling point, but rather a must-have feature that many users expect, if even unknowingly. HTTP/2 is supported by almost all state-of-the-art browsers, including Internet Explorer 11, at least as of Windows 10 [4].
On the major league web servers, however, HTTP/2 has not replaced HTTP/1.1, although it is available in parallel, ensuring downward compatibility with clients that cannot handle HTTP/2 without additional configuration overhead. Another advantage for the system administrator is that important features of HTTP/1.1 remain unchanged in HTTP/2. For example, most HTTP headers and the well-known status codes (1xx, 2xx, …) are the same, as are the request methods (GET
, PUT
, etc.).
The bottom line is that it is high time for operators of websites that do not yet support HTTP/2 to make the jump. In this article, I show you how best to implement HTTP/2 with Nginx.
Nginx and HTTP/2
HTTP/2 is provided in Nginx by the ngx_http_v2_module
module mentioned earlier. You enable it for a server context with the http2
parameter in the listen
directive:
server { listen 443 ssl http2; }
This example reveals one important prerequisite for the use of HTTP/2: The use of Transport Layer Security (TLS), formerly known as Secure Sockets Layer (SSL), is mandatory. HTTP/2 can therefore only be used for encrypted connections between the web browser and the web server because most web browsers request HTTP/2 by Application Layer Protocol Negotiation (ALPN), which in turn is part of TLS. However, this requisite should not be a major hurdle, because an encrypted connection is one of the basic requirements for the secure operation of a web server today. After the launch of Let's Encrypt [5], the creation of a widely accepted TLS certificate has become affordable, even for small projects.
After successfully configuring TLS and adjusting the listen
directive, HTTP/2 is enabled, which could mean the work is done. Important HTTP/2 features such as header compression, request multiplexing, and request pipelining are immediately available without further configuration.
Whether further configuration options are necessary depends in practice on the web server's load. If a web server only needs to process a few access requests per unit of time, it can offer the benefits of HTTP/2 to users without any negative effect. As access increases, however, additional configuration steps may be required, and they differ from the optimizations known for HTTP/1.1.
Optimizing the Configuration
To find the optimal configuration, you must understand the differences in the way HTTP/2 and its predecessor protocols process requests. HTTP protocols before HTTP/2 (i.e., HTTP/1.0, HTTP/1.1) are basically based on the idea of the original HTTP protocol (HTTP/0.9), which assumes that a web browser establishes a dedicated TCP connection to the web server for each request (i.e., for an HTML file, an image, etc.), sends the request, receives the response, and then closes the TCP connection again. With the further development of HTML, however, several requests quickly became necessary to display a complete page in the browser – not only many images, but also additional resources like stylesheets, JavaScript files, tracking pixels, and much more.
To process this flood of requests as quickly as possible with as little latency as possible, web browsers open as many as eight parallel TCP connections to the web server. To reduce the number of TCP connections, HTTP/ 1.1 introduced persistent connections. Additionally, the protocol specifies that web browsers should not establish more than two parallel connections to a web server (but browser vendors tend not to adhere to this).
Nevertheless, it was primarily relevant for the administrator to optimize the configuration of a web server for the highest possible number of simultaneous connections. Moreover, special image domains were often introduced in collaboration with application development (images.<example.com> ) to handle more connections, resulting in pressure on application development to reduce the number of resources required for a website. The result, among other things, was the use of bundling (e.g., with Webpack) and spriting (creating a collage of multiple images in a file that is cut up again in the web browser).
HTTP/2 introduces streams and multiplexing that significantly advance the concept of persistent connections. A single TCP connection between the web browser and the web server can now process any number of requests, even in parallel. The number of concurrent TCP connections is now more or less equal to the number of concurrent users and, therefore, significantly lower compared with previous protocol versions. At the same time, however, the average duration of a TCP connection increases and possibly its memory requirements, as well, because more data traffic is now handled over this one connection.
Buy this article as PDF
(incl. VAT)
Buy ADMIN Magazine
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Most Popular
Support Our Work
ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.