mwhittington

Preparing for HTTP/2

Blog Post created by mwhittington Employee on Oct 13, 2016

By Martin Whittington, Software Engineer DevOps. 23rd July 2015

 

Disclaimer: This work and the technologies are not related to any Alfresco products

 

I claim to be a full-stack developer. I’m happy to work on UI all the way back to server side code. But working on what I call the “OS” layer is something that I don’t get the opportunity to do as often as I’d like. Some of what I’ve done may seem simple or over-complicated to the more trained “Ops” person but I don’t care. If you can do it better, you blog about it!

 

I was recently challenged to configure our web server to be ready for HTTP/2. Luckily, we are using Jetty for one of our internal projects which with its most recent releases is compatible and ready for the new protocol.


These are a summary of the advantages of being ready for HTTP/2:

    • Being able to negotiate between using either HTTP/1.1, HTTP/2 or any other protocol

 

    • Backwards compatibility with HTTP/1.1

 

    • Decreases latency that improves page loading times through several techniques such as:

      • Data compression of HTTP headers

 

      • Server push technologies

 

      • Fixing the head-of-line blocking problem in HTTP 1

 

      • Loading page elements in parallel over a single TCP connection


All of this information can be found at https://en.wikipedia.org/wiki/HTTP/2 so I don’t claim to be an expert, just someone who does their research.

 

These are the steps I took to get us ready for one of our internal applications:

 

Install HAProxy:

 

HAProxy is a free open source solution that provides load balancing and proxying for TCP and HTTP-based applications. The OS I installed this on is OS X Yosemite version 10.10.4 so I used the following code with Homebrew (following the guide at https://www.eclipse.org/jetty/documentation/current/http2-configuring-haproxy.html ):

$ brew update

$ brew install haproxy

But this can be installed either via download or on the Linux command line. Make sure to get the latest version from HAProxy and that, dependant on your OS, the repo’s you download from are kept up to date. If you have any doubts you can download the HAProxy direct from http://www.haproxy.org/download/1.5/src/ or call the following command:

$ sudo apt-get install haproxy

Next I had to create a haproxy.cfg file. A very short and sweet one at that. It’s basically a copy from the link above except for a couple of small changes:

 

global

tune.ssl.default-dh-param 1024
defaults
timeout connect 10000ms
timeout client 60000ms
timeout server 60000ms
frontend fe_http
mode http
bind *:80
# Redirect to https
redirect scheme https code 301
frontend fe_https
mode tcp
bind *:443 ssl no-sslv3 crt domain.pem ciphers TLSv1.2 alpn h2,http/1.1
default_backend be_http
backend be_http
mode tcp
server domain 127.0.0.1:8282

 

I haven’t provided the changes I’ve made on the config file I wrote but I will explain what, at the basic level, needs changing. The first highlighted line needs to be updated to refer to the certificate file of your choice, so domain.pem should be replaced with something.pem.

 

The second highlighted line would just need updating to whatever IP and port your app is running on. Simples!

 

Wherever you decide to save this file is up to you, but I decided to check it into our main code branch. Eventually it will become part of our Chef configuration. Now to run HAProxy all I have to type is:

$ haproxy –f haproxy.cfg (or wherever you file is)

Now if you run the following command:

$ netstat –anlt

You should see HAProxy listening on ports *80 and *443. You will usually see that information at the top of the list.

 

Install Jetty 9.3.1.v20150714:

 

I downloaded the zip archive from http://download.eclipse.org/jetty/ and extracted the archive into /opt/jetty. This is also dependant on java being correctly installed on your system, so make sure you have it installed!! To test that jetty is ready to be configured you can run the following command from the /opt/jetty directory:

$ java –jar start.jar

And you should get a screen like so:

2015-06-04 10:50:44.806:INFO::main: Logging initialized @334ms

2015-06-04 10:50:44.858:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended.  See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html

2015-06-04 10:50:44.995:INFO:oejs.Server:main: jetty-9.3.0.v20150601

2015-06-04 10:50:45.012:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///opt/jetty-distribution-9.3.0.v20150601/webapps/] at interval 1

2015-06-04 10:50:45.030:INFO:oejs.ServerConnector:main: Started ServerConnector@19dfb72a{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}

2015-06-04 10:50:45.030:INFO:oejs.Server:main: Started @558ms

Jetty is ready. The next task is to create a new Jetty Base directory. It is mentioned throughout the Jetty documentation that the Jetty Home directory, in this case /opt/jetty/, be separated from where the apps are deployed. This is infact very simple to setup and requires a line of code at the command prompt (again at the directory you have installed Jetty at):

 

$ jetty   mkdir {new name of base, whatever you want it to be. Name of app is good}
$ cd {new base dir}
$ newDir   java -jar ../start.jar --add-to-start=deploy,http,http2c,https,server,ssl,websocket

 

This initialises the new directory with the modules listed after the –add-to-start parameter. The important one to notice is http2c. This is the module that speaks clear-text HTTP/2. Whether you do or don’t need the other modules is for you to decide based on your requirements.

 

Download a Keystore file (optional)

 

If you have decided to install the SSL module as part of the command to configure your new jetty base directory you will need a keystore file. This can be downloaded from http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/plain/jetty-server/src/test/config/etc/keystore?id=master and once downloaded should be placed in /opt/jetty/{basedir}/etc. That’s it, that parts simple.

 

To make the new base directory accessible by IDE’s and configurable its best to copy of the start.ini file into your new base dir. I achieved this like so:

 

$ basedir      cp ../start.ini .

 

Then any changes you want to make (port changes etc) should be made in the newly copied ini file.

 

IDE Setup

 

There are plenty of IDE’s out there that support the use of creating application servers. I use Intellij Ultimate so I followed the guide here:

 

https://www.jetbrains.com/idea/help/run-debug-configuration-jetty-server.html

 

There are obviously plenty of other guides out there for you to follow based on the IDE you use. Once setup, passing in any JVM options you need, you should have a Jetty server ready for HTTP/2 with HAProxy ready to do its work.

 

Obviously a lot more work needs to go into configuring HAProxy but this blog covers enough so that you are at the starting line for HTTP/2!

Outcomes