Setting up HTTP/2 for Nginx

In Racing Trim

Important Configuration Options

When configuring Nginx, two HTTP/ 2-specific configuration directives come to the fore that let you customize the web server to suit your application.

1. The http2_idle_timeout directive specifies how long an HTTP/2 connection is kept open after the last data exchange. It is comparable to the older keepalive_timeout directive for HTTP/1.1. Even the default values provided by Nginx – 75 seconds for keepalive_timeout, 180 seconds for http2_idle_timeout – show that different use cases have been considered. Although 75 seconds might be considered an average value for potential navigation by the user to the next web page, 180 seconds is more of a maximum value. These times are intended to ensure that any navigation by the user will be handled by the existing connection to the extent possible.

2. The http2_max_requests directive specifies the maximum number of requests that can be processed over a given TCP connection. Again, it parallels HTTP/1.1 (keepalive_requests), and again the default values (100 vs. 1,000) show that the optimization goal has changed significantly.

Both directives are necessary to protect the web server resources. The http2_idle_timeout directive is intended to prevent concurrent connections to the web server from being blocked by clients that don't really need them. Because the amount of memory required per connection grows with the number of requests for that connection, http2_max_requests is intended to prevent a connection from taking up too much memory for itself without actually needing it yet.

Characteristics of a Web App

In common, the two HTTP/2 directives are much more sensitive to the anatomy of the website or application compared with their older counterparts. To illustrate, I will draw on two (extreme) examples: the web version of RFC 7540 [2] and a web application such as Google Docs.

The RFC page is characterized by a minimal number of requests to display the page (the initial HTML document and a graphic as a favicon), a low probability of user navigation (because the page contains few links), and a long viewing time (because the document is very large and thus the reading time tends to be high).

Web applications, on the other hand, have completely different characteristics: Even the display of the first page requires dozens of requests. The multiple interaction options increase the likelihood that the user will navigate. Additionally, XHR requests can be triggered at any time by JavaScript. The user is likely to interact with the page for an extended period of time, which increases the probability that any of these interactions take place.

If you look at these extremes, you can see that correctly chosen configuration values become enormously important in HTTP/2. A very high value for http2_idle_timeout is directly harmful in the case of RFC retrieval, because valuable connections remain unused. For the web application, on the other hand, a very high value directly improves the user experience, because the latency caused by the connection setup can be avoided in the best case.

A high value for http2_max_requests is probably not harmful in the RFC example because the connection is very likely to be terminated before the maximum number of requests is reached. In the case of the web application, however, the advantages of HTTP/2 can only be exploited if the value is set high enough so that at least the initial page setup and the first user interactions can be handled completely after connection, so that no new connection setup is necessary.

These examples show two things: First, HTTP/2 can hardly realize its full potential if the administrator tends to be conservative in configuring it to average values. Second, the configuration is closely related to the application – not all websites are the same.

Moreover, you can also deduce that bundling and spriting have significantly less effect on the speed of a website. Therefore, a cost-benefit analysis with HTTP/2 looks different from that for HTTP/1.1. New projects, especially, might not need a bundling pipeline set up, and the graphics department can dispense with spriting.

Measure, Don't Guess

With HTTP/2, determining the appropriate configuration through measurements becomes more important. Because all modern browsers offer a more or less sophisticated developer console that allows deep insights into the anatomy of a website, metrics are not difficult to come by. In the following example, I use the Chrome developer tools (DevTools).

The Network tab (Figure 1) helps when trying to determine the number of requests for a common user interaction. Here, you select Preserve Log and Disable Cache and then use the search field to restrict the domain you want to examine (e.g., domain:www.linux-magazin.de ). Now you load the website and make typical user actions. In the footer you can read the number of processed requests.

Figure 1: Analysis of web traffic with Chrome DevTools.

The Protocol column, for which you might need to right-click on the column headers, shows that the website is using HTTP/2 (h2 ). In the Connection ID column, you can then see the ID of the TCP connection, which you can use to discover when the browser establishes a new TCP connection.

The marketing department can give you an idea of how long users stay. The usual analysis tools (e.g., Google Analytics) provide good information in this regard. However, do not be deceived by low average values: You might need to look at the power user segment separately.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs



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.

Learn More”>
	</a>

<hr>		    
			</div>
		    		</div>

		<div class=