Welcome to Centmin Mod Community
Register Now

Featured Nginx Nginx HTTP/2 Server Push Finally Supported

Discussion in 'Nginx and PHP-FPM news & discussions' started by eva2000, Feb 13, 2018.

Thread Status:
Not open for further replies.
  1. eva2000

    eva2000 Administrator Staff Member

    53,478
    12,130
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,670
    Local Time:
    3:58 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Nginx 1.13.9 mainline web server release marks the official support for HTTP/2 Server Push - a feature of HTTP/2 which was left out of Nginx HTTP/2 until now. The official Nginx 1.13.9 release has been pushed back by a week due to the HTTP/2 Server Push gzip bug I reported. The HTTP/2 Push gzip bug has been fixed in Nginx master branch so below initial Nginx 1.13.9 HTTP/2 Push tests are using the Nginx master branch code which Centmin Mod 123.09beta01's Nginx upgrade routine supports natively when you specify the Nginx version at upgrade time as = master.

    For most Centmin Mod users, waiting for official Nginx 1.13.9 release is probably best. You can follow Nginx mainline branch roadmap and Nginx release page or Centmin Mod Nginx & PHP-FPM News forums for Nginx release threads.

    When news of HTTP/2 first came out, I was very excited to play with HTTP/2 Server Push as I had already experienced and seen the benefits when testing h2o HTTP/2 web server. So thank you Nginx for finally adding HTTP/2 Server Push support!

    According to HTTP/2 Frequently Asked Questions
    To read more indepth info on what HTTP/2 Server Push is and how it works, you'd want to read the guide at A Comprehensive Guide To HTTP/2 Server Push.

    Want to freshen up on HTTP/2 knowledge ? Check out Youtube video.

    Nginx HTTP/2 Push Directive Documentation



    Nginx HTTP/2 Push directives have also just landed in official Nginx documentation.

    Centmin Mod Nginx HTTP/2 Server Push



    facebook_cmm_nginx-http2-02.png

    Ever since Centmin Mod Nginx 1.9.3 update, HTTP/2 has been supported by Centmin Mod Nginx - first via a HTTP/2 alpha patch in Nginx 1.9.3 posted by Nginx's Valentin V. Bartenev back in August 2015 and then officially when Nginx 1.9.5 anounced HTTP/2 support in September 2015. So let's check out HTTP/2 Server Push support in Centmin Mod built Nginx 1.13.9 web server.

    Centmin Mod 123.09beta01 LEMP stack installer allows end users to upgrade and compile their Nginx server versions via a shell based centmin.sh menu option 4. You just run centmin.sh menu option 4 and when asked which version of Nginx you want to upgrade or downgrade to, just type the version in i.e. 1.13.9 when it's officially released or type the word = master to pull and compile from Nginx master branch and then watch Centmin Mod compile and install that version for you :)

    You'll want to always use latest Nginx mainline version listed at nginx: download

    Code (Text):
    --------------------------------------------------------
         Centmin Mod Menu 123.09beta01 centminmod.com
    --------------------------------------------------------
    1).  Centmin Install
    2).  Add Nginx vhost domain
    3).  NSD setup domain name DNS
    4).  Nginx Upgrade / Downgrade
    5).  PHP Upgrade / Downgrade
    6).  XCache Re-install
    7).  APC Cache Re-install
    8).  XCache Install
    9).  APC Cache Install
    10). Memcached Server Re-install
    11). MariaDB MySQL Upgrade & Management
    12). Zend OpCache Install/Re-install
    13). Install/Reinstall Redis PHP Extension
    14). SELinux disable
    15). Install/Reinstall ImagicK PHP Extension
    16). Change SSHD Port Number
    17). Multi-thread compression: pigz,pbzip2,lbzip2...
    18). Suhosin PHP Extension install
    19). Install FFMPEG and FFMPEG PHP Extension
    20). NSD Install/Re-Install
    21). Update - Nginx + PHP-FPM + Siege
    22). Add Wordpress Nginx vhost + Cache Plugin
    23). Update Centmin Mod Code Base
    24). Exit
    --------------------------------------------------------
    Enter option [ 1 - 24 ] 4
    --------------------------------------------------------
    

    Code (Text):
    **********************************************************************
    * Nginx Update script - Included in Centmin Extras
    * Version: 123.09beta01.b013 - Date: 31/01/2018 - Copyright 2011-2018 CentminMod.com
    **********************************************************************
    
    This software comes with no warranty of any kind. You are free to use
    it for both personal and commercial use as licensed under the GPL.
    
    
    Nginx Upgrade - Would you like to continue? [y/n] y
    
    Install which version of Nginx? (version i.e. type 1.13.8): 1.13.9
    

    Once Centmin Mod finishes building Nginx 1.13.9, the end resulting configured Nginx would be something like below when you check Nginx version output. Centmin Mod Nginx supports various compilers from GCC 4, 5.3, 6.3, 7.2, 8.x and Clang 3.4, 4, 5 and 6. Below is with GCC 8.0.1 compiler and OpenSSL 1.1.1-pre1 alpha which I am currently testing for TLS 1.3 support (2 birds and 1 stone and all that :) ).

    Nginx Cache Aware HTTP/2 Server Push



    To test Nginx 1.13.9 HTTP/2 Server Push, I implemented the suggestion by Smashing Magazine to implement a form of web browser cache aware HTTP/2 Server Push by using conditional preload link resource hint headers which only get served if a preset cookie is not present (pushcheck=visited) and using nginx mapping of $cookie_pushcheck to add the preload link header via add_header directives. Basically, only serve preload link resource hint headers for HTTP/2 Server Push if a preset cookie doesn't exist - which implies a first time visitor who doesn't have pushed assets within their web browser cache. Repeat visitor and page reloads, will skipp adding the preload link headers in favour of serving the previously pushed assets via the visitor's web browser cache.

    Apache’s mod_http2 uses the H2PushDiarySize and H2O HTTP/2 server has http2-casper directive for similar cache aware HTTP/2 Server push implementations. I am not aware of any Nginx native implementation, so this is one workaround I came up with.

    Curl header check for test HTTP/2 Server Pushed domain.
    Code (Text):
    curl -I https://http2.centminmod.com/
    HTTP/2 200
    date: Thu, 15 Feb 2018 17:49:07 GMT
    content-type: text/html; charset=utf-8
    content-length: 6103
    last-modified: Sun, 11 Feb 2018 01:14:19 GMT
    vary: Accept-Encoding
    etag: "5a7f98eb-17d7"
    server: nginx centminmod
    x-powered-by: centminmod
    set-cookie: pushcheckp=puremin
    set-cookie: pushcheckt=grid
    link: </purecss/pure-min.css>; rel=preload; as=style
    link: </purecss/grids-responsive-min.css>; rel=preload; as=style
    accept-ranges: bytes
    

    I setup two CSS files to be HTTP/2 Server Pushed via preload link resource hint headers
    Code (Text):
    link: </purecss/pure-min.css>; rel=preload; as=style
    link: </purecss/grids-responsive-min.css>; rel=preload; as=style
    

    The two additional cookies added to check if visitor is a first time visitor or repeat (for browser cache skipping)
    Code (Text):
    set-cookie: pushcheckp=puremin
    set-cookie: pushcheckt=grid
    

    On the Nginx nginx.conf end the relevant nginx mapped cookies to determine whether or not Nginx should serve a preload link resource hint header to visitors based on presence or absence of preset cookies
    Code (Text):
    map $cookie_pushcheckp $push_cookiepuremin {
       default "</purecss/pure-min.css>; rel=preload; as=style";
       "~*puremin" '';
    }
    
    map $cookie_pushcheckt $push_cookiegrid {
       default  "</purecss/grids-responsive-min.css>; rel=preload; as=style";
       "~*grid" '';
    }
    

    Nginx vhost end with HTTP/2 Push enabled via http2_push_preload directive and additional preset cookies.
    Code (Text):
    location /  {
       http2_push_preload on;
       add_header Set-Cookie "pushcheckp=puremin";
       add_header Set-Cookie "pushcheckt=grid";
       add_header Link $push_cookiepuremin;
       add_header Link $push_cookiegrid;
    }
    


    nghttp stats output * next to pushed CSS files indicates HTTP/2 Server Push
    Code (Text):
    nghttp -nas https://http2.domain.com/
    
    ***** 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     +1.27ms       +141us   1.13ms  200   1K /
      2     +1.63ms *     +411us   1.22ms  200   4K /purecss/pure-min.css
      4     +2.08ms *     +449us   1.64ms  200   1K /purecss/grids-responsive-min.css
    


    Looks like Nginx HTTP/2 Server Push supports multiple preload hints headers within same add_header directive which makes it easier to use one cookie for detection according to Nginx blog at Introducing HTTP/2 Server Push with NGINX 1.13.9 | NGINX

    So change above to

    Code (Text):
    map $cookie_pushcheck $push_cookie {
       default "</purecss/pure-min.css>; rel=preload; as=style, </purecss/grids-responsive-min.css>; rel=preload; as=style";
       "~*pushed" '';
    }
    

    Nginx vhost end with HTTP/2 Push enabled via http2_push_preload directive and additional preset cookies.
    Code (Text):
    location /  {
       http2_push_preload on;
       add_header Set-Cookie "pushcheck=pushed";
       add_header Link $push_cookie;
    }
    

     
  2. eva2000

    eva2000 Administrator Staff Member

    53,478
    12,130
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,670
    Local Time:
    3:58 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+

    Nginx Cache Aware HTTP/2 Server Push



    Testing my above outlined cache aware Nginx 1.13.9 HTTP/2 Server Push using custom cookie detection. First load has pushed initiator column CSS files where Nginx detects no custom cookies. Second reload is when Nginx detects custom cookies and assumes repeat visit, so skip HTTP/2 Push.

    cache-aware-http2-push.gif

    There are probably other ways of implementing browser cache aware HTTP/2 Server Pushes. Maybe using a single cookie that is a fingerprint hash of pushed static file assets ? So if you have other ideas please share :)

    Following tests where done in Chrome Canary web browser on Windows 10

    First time visitor without preset cookie detected will be served HTTP/2 Pushed CSS files

    cmm-nginx-1.13.9-openssl111pre1-gcc721-http2push-devtools-01.png

    Inspecting the 2 CSS files HTTP/2 Pushed timings

    cmm-nginx-1.13.9-openssl111pre1-gcc721-http2push-devtools-02.png
    cmm-nginx-1.13.9-openssl111pre1-gcc721-http2push-devtools-03.png
    Then reloading the page will detect that this is a repeat visitor as the presence of the preset cookies are detected so skip server HTTP/2 Pushed CSS files and serve from visitor's web browser cache instead.

    cmm-nginx-1.13.9-openssl111pre1-gcc721-http2push-devtools-04.png

    Inspecting timings for CSS files served from web browser (disk cache)

    cmm-nginx-1.13.9-openssl111pre1-gcc721-http2push-devtools-05.png
    cmm-nginx-1.13.9-openssl111pre1-gcc721-http2push-devtools-06.png
     
  3. eva2000

    eva2000 Administrator Staff Member

    53,478
    12,130
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,670
    Local Time:
    3:58 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+

    Webpagetest.org HTTP/2 Server Push Tests



    Next up moving Nginx HTTP/2 Server Push testing to Webpagetest.org. For noobs WebPerf - PageSpeed - How to use webpagetest.org for page load speed testing :)

    Using Chrome Cable 5Mbps profile with California location server

    First view mean profile

    upload_2018-2-16_20-22-54.png

    Waterfall and index page's response header

    upload_2018-2-16_20-23-32.png

    Not sure why when using Webpagetest and you check first and repeat view for run parameters, the repeat view returns error for Test Data Missing ?

    upload_2018-2-16_20-28-14.png
     
  4. eva2000

    eva2000 Administrator Staff Member

    53,478
    12,130
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,670
    Local Time:
    3:58 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Official blog Introducing HTTP/2 Server Push with NGINX 1.13.9 | NGINX. Yes final Nginx 1.13.9 version has been officially released. Centmin Mod users can discuss Nginx 1.13.9 here.

    Nginx 1.13.9 final release + GCC 8.0.1 Feb 18th build release + OpenSSL 1.1.1-pre1 alpha release for TLS v1.3 + Cloudflare zlib performance patch + ngx_pagespeed 1.13.35.2-stable + Cloudflare HTTP/2 HPACK Full Encoding patch
     
Thread Status:
Not open for further replies.