Nginx HTTP/2 protocol to replace Google SPDY
Centmin Mod 1.2.3-eva2000.09 beta (123.09beta01 branch) added support for Nginx's new HTTP/2 alpha patch [nginx.com] which supports h2 Application Layer Protocol Negotiation (ALPN) TLS extensions. Installing the Nginx HTTP/2 patch or final releases will remove SPDY module support in Nginx. Unfortunately, the HTTP/2 patch or first production release will not support HTTP/2 Server Push feature but future versions may. The Nginx HTTP/2 patch was cosponsored by Dropbox and Automattic. HTTP/2 protocol will be replacing Google's SPDY protocol in early 2016.
Backported Nginx HTTP/2 support
Nginx 1.9.5 seems to be the version which officially support Nginx HTTP/2. Even the official Nginx HTTP/2 documentation is already in place. For Centmin Mod Nginx, Nginx HTTP/2 supported routines have been backported from Centmin Mod 1.2.3-eva2000.09 beta to 1.2.3-eva2000.08 stable branch as at September 18th, 2015. So ensure you update Centmin Mod code as outlined on Upgrade page before updating to Nginx 1.9.5 via centmin.sh menu option 4
Nginx HTTP/2 Patch Updates
Nginx HTTP/2 patch version updates can be found at here. Centmin Mod 1.2.3-eva2000.09 beta will automatically apply the latest Nginx HTTP/2 patch when you run centmin.sh menu option 4
to upgrade/recompile Nginx 1.9.3+ and higher versions.
2015-09-11 Version 6 (NGINX 1.9.4) - Sending GOAWAY frame on connection shutdown; - Proper handling of huge response headers using CONTINUATION frames; - Various minor fixes. 2015-09-08 Version 5 (NGINX 1.9.4) - Validation of the request headers; - Improved error handling even more; - Added the http2_max_header_size directive that limits the maximum size of a request headers (16384 bytes by default); - Fixed the default value of the http2_max_field_size directive; - Limited consumption of memory during the HTTP/2 session; - The $request_line variable for HTTP/2 requests now uses "HTTP/2.0" as the version token instead of "HTTP/1.1". 2015-08-31 Version 4 (NGINX 1.9.4) - Improved error handling; - Added the http2_max_field_size directive that limits the maximum size of a request header field (4096 bytes by default); - The http2_keepalive_timeout directive was renamed to http2_idle_timeout. 2015-08-19 Version 3 (NGINX 1.9.4) - The gzip and gzip_static modules might not work with HTTP/2 requests; - Fixed processing of Cookie headers. 2015-08-14 Version 2 (NGINX 1.9.3) - Introduced NPN support for HTTP/2 negotiation (this reduces OpenSSL version requirement to 1.0.1+); - Various fixes in the prioritization mechanism; - Fixed missing "Location" response header in some configurations; - Fixed processing of the ":authority" pseudo-header (the HTTP/2 analog of the "Host" header). 2015-08-05 Version 1 (NGINX 1.9.3) The first public alpha release.
Nginx HTTP/2 vs Nginx SPDY
After applying Nginx HTTP/2 patch or updating to Nginx 1.9.5+ and higher for HTTP/2 support, Nginx SPDY module will be removed. This means there are a few technical changes to your Nginx vhost configurations you need to make for HTTP/2 to work.
listen directive changes with replacing spdy
with http2
parameter
listen 443 ssl spdy;
becomes
listen 443 ssl http2;
If you do not replace the listen directive and have Nginx HTTP/2 compiled, you will receive an error on Nginx restart similar to the one below.
ngxrestart nginx: [emerg] invalid parameter "spdy": the SPDY module was deprecated, use the HTTP/2 module instead in /usr/local/nginx/conf/conf.d/newdomain.com.ssl.conf:15 nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
Some SPDY specific options will need to be removed for Nginx HTTP/2 patched server to start up properly. These options include:
- spdy_headers_comp - HTTP/2 doesn't use gzip compression but HPACK for header compression.
- spdy_keepalive_timeout
Error on Nginx restart after HTTP/2 patch applied for unsupported SPDY options
nginx: [emerg] unknown directive "spdy_keepalive_timeout"
There are optional HTTP/2 configuration directives for Nginx:
http2_recv_buffer_size
(http) specifies the size of input buffer per worker (256k by default).http2_max_concurrent_streams
(http, server) sets the maximum number of concurrent HTTP/2 streams in a single connection (128 by default).http2_streams_index_size
(http, server) configures the size of the HTTP/2 stream ID index; must be a power of 2 (default is 32).http2_recv_timeout
(http, server) defines the timeout when expecting more data from the client (default is 30s).http2_keepalive_timeout
(http, server) sets the inactivity timeout after which the connection is closed (default is 3m).http2_chunk_size
(http, server, location) defines the default DATA frames size for response body (default is 8k).
HTTP/2 variable:
$http2
negotiated protocol identifier if the request came via HTTP/2 ("h2", "h2c"), or empty value.
HTTP/2 Browser Compatibility
HTTP/2 browser compatibility isn't as wide spread compared to SPDY right now according to information at caniuse.com.
SPDY Browser Compatibility
HTTP/2 Browser Compatibility
Nginx HTTP/2 Tools
For command line testing for HTTP/2 sites, some of the tools like h2spec, nghttp2, h2i, cipherscan, ssllabs-scan, testssl, curl with --http2 support, openssl 1.0.2 with chacha20_poly1305 cipher support are bundled into my Docker Ubuntu Vivid nghttp2 container bundle. Included in nghttp2 is a HTTP/2 and SPDY supported benchmarking load testing tool h2load.
Nginx HTTP/2 Benchmarks
Below tests were done with Nginx HTTP/2 version 1 of the alpha patch. Nginx HTTP/2 version 2 of alpha patch has just been released and all centminmod.com servers have been updated to Nginx HTTP/2 version 2 patch. It seems that Nginx HTTP/2 version 2 of the patch has also fixed some of my Nginx HTTP/2 + ngx_pagespeed issues and now ngx_pagespeed works ! However, webpagetest.org does still report Error: Timed Out either on First View or Repeat View tests stage. You can find Nginx HTTP/2 version 2 patch benchmark results here.
2015-08-14 Version 2 (NGINX 1.9.3) - Introduced NPN support for HTTP/2 negotiation (this reduces OpenSSL version requirement to 1.0.1+); - Various fixes in the prioritization mechanism; - Fixed missing "Location" response header in some configurations; - Fixed processing of the ":authority" pseudo-header (the HTTP/2 analog of the "Host" header). 2015-08-05 Version 1 (NGINX 1.9.3) The first public alpha release.
Working Nginx HTTP/2 + ngx_pagespeed!
nghttp -nas https://centminmod.com:443 ***** Statistics ***** Request timing: responseEnd: the time when last byte of response was received relative to connectEnd requestStart: the time just before first byte of request was sent relative to connectEnd. If '*' is shown, this was pushed by server. process: responseEnd - requestStart code: HTTP status code size: number of bytes received as response body without inflation. URI: request URI see http://www.w3.org/TR/resource-timing/#processing-model sorted by 'complete' id responseEnd requestStart process code size request path 13 +80.22ms +532us 79.69ms 200 29K / 15 +91.08ms +66.98ms 24.10ms 200 9K /img/favicon.ico 17 +125.17ms +66.99ms 58.18ms 200 60K /css/A.localfonts.css+font-awesome.min.css+bootstrap.min.css+hover-dropdown-menu.css+icons-set8.css+animate.min.css+style.css+responsive.css+color.css,Mcc.FHj-r4A0cI.css.pagespeed.cf.YOn5Xvomna.css 21 +141.41ms +66.99ms 74.42ms 200 7K /js/hover-dropdown-menu.js+jquery.hover-dropdown-menu-addon.js+jquery.easing.1.3.js.pagespeed.jc.vy5S6wKQse.js 25 +156.83ms +67.03ms 89.81ms 200 6K /js/custom.js.pagespeed.jm.q-StvNlmtR.js 19 +157.11ms +66.99ms 90.11ms 200 38K /js/jquery.min.js+bootstrap.min.js.pagespeed.jc.Cd39AMnoIp.js 23 +157.12ms +67.02ms 90.09ms 200 24K /js/bootstrapValidator.min.js.pagespeed.jm.YU3KUlvaHb.js
Centmin Mod 123.09beta01 Nginx compile options with --with-http_v2_module
:
nginx -V nginx version: nginx/1.9.3 built by clang 3.4.2 (tags/RELEASE_34/dot2-final) built with LibreSSL 2.2.2 TLS SNI support enabled configure arguments: --with-ld-opt='-lrt -ljemalloc -Wl,-z,relro -Wl,-rpath,/usr/local/lib' --with-cc-opt='-m64 -mtune=native -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wno-deprecated-declarations -Wno-unused-parameter -Wno-unused-const-variable -Wno-conditional-uninitialized -Wno-mismatched-tags -Wno-c++11-extensions -Wno-sometimes-uninitialized -Wno-parentheses-equality -Wno-tautological-compare -Wno-self-assign -Wno-deprecated-register -Wno-deprecated -Wno-invalid-source-encoding -Wno-pointer-sign -Wno-parentheses -Wno-enum-conversion' --sbin-path=/usr/local/sbin/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_sub_module --with-http_addition_module --with-http_image_filter_module --with-http_secure_link_module --with-http_realip_module --with-http_geoip_module --with-openssl-opt=enable-tlsext --add-module=../ngx-fancyindex-ngx-fancyindex --add-module=../ngx_cache_purge-2.3 --add-module=../nginx-accesskey-2.0.3 --add-module=../nginx-http-concat-master --add-module=../openresty-memc-nginx-module-4f6f78f --add-module=../openresty-srcache-nginx-module-ffa9ab7 --add-module=../ngx_devel_kit-0.2.19 --add-module=../set-misc-nginx-module-0.29 --add-module=../echo-nginx-module-0.58 --add-module=../redis2-nginx-module-0.12 --add-module=../ngx_http_redis-0.3.7 --add-module=../lua-nginx-module-0.9.16 --add-module=../lua-upstream-nginx-module-0.03 --add-module=../lua-upstream-cache-nginx-module-0.1.1 --add-module=../nginx_upstream_check_module-0.3.0 --add-module=../nginx-module-vts --add-module=../headers-more-nginx-module-0.261 --with-openssl=../libressl-2.2.2 --with-libatomic --with-threads --with-stream --with-stream_ssl_module --with-pcre=../pcre-8.37 --with-pcre-jit --add-module=../ngx_pagespeed-release-1.9.32.6-beta
- Nginx HTTP/2 World Flags Demo HTTP/2 vs HTTP/1.1 (Nginx HTTP/2 version 1 patched)
- Nginx HTTP/2 World Flags Demo extended HTTP/2 vs SPDY/3.1 vs HTTP/1.1 (Nginx HTTP/2 version 1 & 2 patched)
- Testing Nginx HTTP/2 (Nginx HTTP/2 version 1 patched)
- WebPageTest.org Testing Nginx HTTP/2 (Nginx HTTP/2 version 1 patched)
Nginx HTTP/2 World Flags Demo
I've recreated a Nginx HTTP/2 World Flags Demo page so folks can check out and compare both Nginx HTTP/2 vs non-HTTP/2 performance. Note for Nginx HTTP/2 + ngx_pagespeed enabled (which is broken) webpagetest.org test first view results in a timeout eventually, so could be related to ngx_pagespeed not working with Nginx HTTP/2 patch. Update: also added a Nginx HTTP/2 World Flags Demo extended test with Nginx HTTP/2 vs Nginx SPDY/31 vs Nginx HTTP/1.1.
- http://centminmod.com/flags/ -
HTTP/1.1
non-https + ngx_pagespeed enabled [webpagetest.org result] - http://centminmod.com/flags/?PageSpeed=off -
HTTP/1.1
non-https + ngx_pagespeed disabled [webpagetest.org result] - https://centminmod.com/flags/ -
HTTP/2
https + ngx_pagespeed enabled but broken (HTTP/2 patch broke ngx_pagespeed) [webpagetest.org result] - https://centminmod.com/flags/?PageSpeed=off -
HTTP/2
https + ngx_pagespeed disabled [webpagetest.org result]
4-way WebPageTest.org comparison from Los Angeles location with Chrome 3G Mobile 300ms RTT connection speed and 1920x1200 resolution window. All 3rd party scripts were blocked for testing purposes.
The Nginx HTTP/2 vs non-HTTP/2 results with ngx_pagespeed confirmed the same results I had when I tested h2o HTTP/2 and OpenLiteSpeed HTTP/2 World Country Flags tests. Nginx HTTP/1.1 + ngx_pagespeed
was still the fastest combination, then Nginx HTTP/2 + ngx_pagespeed
(even if it was broken), then Nginx HTTP/2
and slowest by far was Nginx HTTP/1.1 with ngx_pagespeed disabled
.
Testing Nginx HTTP/2
Both centminmod.com site and sslspdy.com sitess have had their Centmin Mod LEMP versions updated to 123.09beta01 branch with Nginx 1.9.3 patched with HTTP/2 support. You can check out both site's HTTP/2 implements on the https://
version of the sites:
- https://centminmod.com - Nginx HTTP/2 using RSA 2048 bit Wildcard SSL certificate
- https://sslspdy.com - Nginx HTTP/2 using Elliptic Curve Cryptography ECC 256 bit Wildcard SSL certificate
There are Chrome and Firefox extensions and plugins for HTTP/2 & SPDY Indicators you can install.
You can also use Chrome or Firefox Developer Tools to enable the protocol display field in Network tab.
Checking the ALPN protocol returns h2 for HTTP/2
openssl s_client -alpn h2 -host centminmod.com -port 443 New, TLSv1/SSLv3, Cipher is ECDHE-RSA-CHACHA20-POLY1305 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE ALPN protocol: h2 SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-CHACHA20-POLY1305
openssl s_client -alpn h2 -host sslspdy.com -port 443 New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-CHACHA20-POLY1305 Server public key is 256 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE ALPN protocol: h2 SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-ECDSA-CHACHA20-POLY1305
Using h2i tool to check.
h2i centminmod.com Connecting to centminmod.com:443 ... Connected to 104.152.214.227:443 Negotiated protocol "h2" [FrameHeader SETTINGS len=18] [MAX_CONCURRENT_STREAMS = 128] [INITIAL_WINDOW_SIZE = 2147483647] [MAX_FRAME_SIZE = 16777215] [FrameHeader WINDOW_UPDATE len=4] Window-Increment = 2147418112
h2i sslspdy.com Connecting to sslspdy.com:443 ... Connected to 192.184.89.66:443 Negotiated protocol "h2" [FrameHeader SETTINGS len=18] [MAX_CONCURRENT_STREAMS = 128] [INITIAL_WINDOW_SIZE = 2147483647] [MAX_FRAME_SIZE = 16777215] [FrameHeader WINDOW_UPDATE len=4] Window-Increment = 2147418112
Using custom compiled curl 7.43+ with nghttp2 support which allows the curl --http2
flag option to test over HTTP/2 connection.
curl -I --http2 https://centminmod.com -v * Rebuilt URL to: https://centminmod.com/ * Trying 104.152.214.227... * Connected to centminmod.com (104.152.214.227) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Using Stream ID: 1 (easy handle 0x117f5a0) > HEAD / HTTP/1.1 > Host: centminmod.com > User-Agent: curl/7.43.0-DEV > Accept: */* > * http2_recv: 16384 bytes buffer at 0x117fef0 (stream 1) * Connection state changed (MAX_CONCURRENT_STREAMS updated)! * http2_recv: 16384 bytes buffer at 0x117fef0 (stream 1) * http2_recv: 16384 bytes buffer at 0x117fef0 (stream 1) * http2_recv: returns 247 for stream 1 < HTTP/2.0 200 HTTP/2.0 200
Checking HTTP/2 via nghttp2 tool itself over HTTP/2 connection
nghttp -nv https://centminmod.com:443 [ 0.063] Connected The negotiated protocol: h2 [ 0.097] recv SETTINGS frame(niv=3) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):128] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):2147483647] [SETTINGS_MAX_FRAME_SIZE(0x05):16777215]
nghttp stats
nghttp -nas https://centminmod.com:443 ***** Statistics ***** Request timing: responseEnd: the time when last byte of response was received relative to connectEnd requestStart: the time just before first byte of request was sent relative to connectEnd. If '*' is shown, this was pushed by server. process: responseEnd - requestStart code: HTTP status code size: number of bytes received as response body without inflation. URI: request URI see http://www.w3.org/TR/resource-timing/#processing-model sorted by 'complete' id responseEnd requestStart process code size request path 13 +35.99ms +316us 35.67ms 200 10K / 15 +45.66ms +36.04ms 9.62ms 200 9K /img/favicon.ico 17 +46.15ms +36.05ms 10.10ms 200 1K /css/localfonts.css 19 +54.87ms +36.05ms 18.82ms 200 5K /css/font-awesome.min.css 21 +63.82ms +36.05ms 27.77ms 200 19K /css/bootstrap.min.css 23 +64.07ms +36.05ms 28.01ms 200 4K /css/hover-dropdown-menu.css 25 +64.12ms +36.05ms 28.06ms 200 569 /css/icons-set8.css 27 +70.11ms +36.06ms 34.05ms 200 3K /css/animate.min.css 29 +79.33ms +36.06ms 43.27ms 200 24K /css/style.css 31 +79.51ms +36.06ms 43.45ms 200 2K /css/responsive.css 33 +79.56ms +36.07ms 43.49ms 200 1K /css/color.css 35 +88.28ms +36.07ms 52.21ms 200 29K /js/jquery.min.js 37 +88.81ms +36.07ms 52.74ms 200 9K /js/bootstrap.min.js 39 +89.04ms +36.07ms 52.96ms 200 6K /js/hover-dropdown-menu.js 41 +89.07ms +36.07ms 52.99ms 200 985 /js/jquery.hover-dropdown-menu-addon.js 43 +89.10ms +36.07ms 53.02ms 200 797 /js/jquery.easing.1.3.js 47 +92.29ms +36.08ms 56.22ms 200 8K /js/custom.js 45 +101.77ms +36.08ms 65.69ms 200 25K /js/bootstrapValidator.min.js
WebPageTest.org Testing Nginx HTTP/2
Webpagetest.org comparison test for centminmod.com for testing HTTP/1.1 + ngx_pagespeed, HTTP/1.1 + ngx_pagespeed disabled and HTTP/2 without ngx_pagespeed. This site probably isn't the best example for HTTP/2 or ngx_pagespeed usage due to minimalistic design. The more page elements - js, css, and images the page has, the greater the benefit HTTP/2 and SPDY would have. Just bare that in mind.