Using the HTTP/2 protocol
HTTP was invented by Tim Berners-Lee in 1989 while he was working at CERN. It was designed as a way to share scientific findings among coworkers and is almost three decades old. When HTTP was invented, it was never intended to be the backbone of today's low-latency, high-traffic web, used by millions if not billions of people. So HTTP 1-and HTTP 1.1-based web applications had to have a lot of workarounds to cater to the high demands of the modern web. The following are some of those workarounds:
- Concurrent resources are download by the browser since HTTP 1.x can download only one resource at a time, and Domain Sharding is used to tackle limitations on the maximum number of connections per domain
- Combining multiple resources such as CSS/Javascript files together with complex server-side logic and downloading them all in one go
- Multiple image sprites in a single resource to reduce the number of image file downloads
- Inlining static resources in an HTML file itself
But HTTP/2 is designed from the ground up to tackle these pain points. Compared to HTTP 1.x, HTTP/2 doesn't use text to communicate between the client and server. It uses binary data frames, which makes it much more efficient and reduces the text-to-binary and binary-to-text conversion overhead in the servers. Furthermore, it has the following features introduced:
- HTTP/2 multiplexing: This multiplexing feature allows opening one connection to a server and downloading multiple resources using that connection:
- HTTP/2 push: This will send resources to clients even before resources are requested:
- HTTP/2 header compression: Eliminates the repeating of the same headers across multiple requests by maintaining an HTTP header table, thus reducing request bandwidth
Spring Boot 2 supports HTTP/2 out of the box for server Undertow, and, with minor dependencies at https://docs.spring.io/spring-boot/docs/2.0.x-SNAPSHOT/reference/htmlsingle/#howto-configure-http2, also supports Tomcat and Jetty servers. But Spring Boot 2 doesn't support the clear text version of HTTP/2, so Secure Socket Layer (SSL) is a must. It requires the following dependencies in pom.xml :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
...
</dependencies>
The configuration properties in application.yml configure both SSL and HTTP/2:
server:
port: 8443
ssl:
key-store: keystore.p12
key-store-password: sslcert123
keyStoreType: PKCS12
keyAlias: sslcert
http2:
enabled: true
In this configuration SSL key-store, key-store-password, keyStoreType, and keyAlias are configured along with the port for HTTPs. The key was generated using keytool, which is a utility shipped with the JDK release with the following command, and fills in the necessary details when prompted by the utility tool:
$ keytool -genkey -alias sslcert -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
Now when the https://<localhost>:8443/actuator/custom URL is accessed it will be served over HTTP/2.