HTTP/2 on SAP BTP, Cloud Foundry runtime
SAP BTP, Cloud Foundry runtime now supports HTTP/2 🎉. This feature is available for everyone who has deployed an app to the platform. In this blog post we will cover what you need to know before using HTTP/2 and how you can enable it for you application.
What is HTTP/2
HTTP/2 is the next major version of the HTTP protocol. The connection handling and request handling have been completely reworked and are incompatible with HTTP/1. However, this allows many major improvements to make the best use of modern internet connections and optimise resource usage. Websites often load many different resources and make lots of API calls which sometimes block each other. With HTTP/2 these issues have been partially addressed to allow for much better performance.
The more small resources are loaded and the more long-running API calls an application has, the more it will benefit from using HTTP/2.
These are the most notable changes:
With HTTP/1 most browsers make a maximum of six parallel connections to a server. This is done to avoid a single, slow request blocking all other requests (head of line blocking). If the application makes more than six requests at any given time some requests will have to wait for others to complete. Most of the time there is no proper control over the order in which requests are executed which can lead to resources that are not needed immediately blocking other more important files that are required to display an initial loading page to the user.
HTTP/2 solves this issue by multiplexing requests over a single connection. This saves resources on client and server side without blocking requests. Clients will send all request immediately and the server will answer them as soon as the response is ready. This also allows prioritising requests and decide which resources need to be presented first.
Instead of sending the same headers over and over again, as it is the case with HTTP/1, HTTP/2 re-uses previously sent headers. Client and server keep track of the headers that were already sent/received and only headers that have changed (compared to the previous request) will be sent again. This is one of many steps to reduce the size of each request and therefore utilise the available bandwidth as efficiently as possible.
In order to achieve these new functionalities, HTTP/2 had to move away from the text based approach. HTTP/2 now consists of individual frames that make up a full message (request/response). These frames are sent as binary data and therefore cannot be read by a human which can complicate debugging (however, that was already the case with compression in HTTP/1). The frames are organised into streams, each of which can carry one or more messages. The streams can also be prioritised to make sure more important resources are served first.
Due to the incompatibility with HTTP/1, the client and server need to negotiate a protocol before they send data which is usually done during the TLS handshake. During the handshake, the client and server can offer their available versions using Application-Layer Protocol Negotiation (ALPN) which is an extension to TLS.
Since there can also be traffic that does not use TLS but still wants to benefit from HTTP/2 there are two kinds of HTTP/2. HTTP/2 over TLS (also referred to as
h2) and HTTP/2 over cleartext (also referred to as
h2c uses different mechanisms to negotiate the protocol, one is described in section “From the platform to your apps” below.
On top of this new protocol a modern remote procedure calling (RPC) framework has been built: gRPC (gRPC Remote Procedure Calls). It was designed to work in distributed systems with low latency and independent of the underlying programming language (Java, Go, Ruby, …) or the content type of the request (JSON, XML, protobuf, …). By default, it’s using protobuf as the content type which, together with the protoc compiler, allows the developer to generate server and client code in multiple languages from a single definition. You can read more about it on the projects’ website. In order to achieve its goals gRPC utilises HTTP/2 which was built to carry multiple independent streams over a single connection and keep each connection alive as long as possible.
How to enable it on SAP BTP, Cloud Foundry runtime
Before we explain how to enable HTTP/2 for your application please note that currently we do NOT support web sockets over HTTP/2. The HTTP/2 specification includes support for web sockets but due to constraints on internal components of the routing stack we cannot support web sockets on HTTP/2 as of now. However, this might change in the future.
Requests coming into the platform
To benefit from the performance improvements HTTP/2 has over HTTP/1 for requests coming into the platform, for example from browsers, you need to use the Custom Domain Service. This service allows you to use your own domain for apps running on the platform and configure how clients can connect to your custom domain. As well as allowing you to configure custom TLS options, there is a simple checkbox to enable HTTP/2 for requests to your custom domain.
To learn how to set up the Custom Domain Service, please refer to this SAP Help Portal article: Custom Domain Manager – Initial Setup. After the domain is set up you can configure HTTP/2 support by specifying a TLS Configuration as explained in Custom Domain Manager – Manage TLS Configuration. The HTTP/2 option is part of the TLS configuration because the protocol is negotiated during the TLS handshake (as explained above).
When this is enabled, requests to the platform will now use HTTP/2 if the client supports it but requests from the platform to your application will still use HTTP/1. This way you can benefit from performance improvements of HTTP/2 when your users make requests from their browsers without having to re-architect your applications to support HTTP/2.
From the platform to your apps
If you want to use the more advanced features of HTTP/2 such as gRPC or server push, you need to enable HTTP/2 on the application side as well. A major benefit of Cloud Foundry is that TLS termination is handled for you and you don’t need to worry about implementing TLS in your application. As the platform manages encryption for you when you enable HTTP/2 for requests from the platform to your apps, requests are sent unencrypted (just like with HTTP/1). This plaintext version of HTTP/2 is known as
h2c and less popular than versions of HTTP/2 involving TLS, however there is still support for
h2c in most programming languages (see Sample Apps below).
Enabling HTTP/2 for a Cloud Foundry app is fairly easy. You either specify it as part of the manifest:
--- ... routes: - route: example.com protocol: http2
Or you can specify it in the
# Requires CF CLI version 8 or higher cf map-route MY-APP EXAMPLE.COM --hostname EXAMPLE --destination-protocol http2
Please note that the app will receive only
h2c traffic from this route and is expected to be able to handle such traffic. Specifically, the platform will send requests using the “h2c with prior knowledge” as specified in RFC-7540 section 3.4. It will first send the client connection preface which informs the application that from now on traffic will be
h2c. The preface looks like this (newlines are
PRI * HTTP/2.0 SM
The main goal was to make the preface compatible with HTTP/1 servers but use a series of characters that is unlikely to appear in real HTTP/1 communication. This allows a server to handle both (HTTP/1 and HTTP/2) by having a special handler for this HTTP/1 message which starts
h2c communication. After the client connection preface the server is expected to send the server connection preface which consists of a SETTINGS frame. More details on this topic can be found in RFC-7540 section 3.4. Most of the time this handling will be done as part of the server implementation that you are using.
If the route supports HTTP/2 end-to-end (e.g. with custom domain and app side
h2c) you will be able to use the more advanced features of HTTP/2 like gRPC or server push. The routing stack is able to dynamically switch internally to truly support HTTP/2 end-to-end.
Sample apps for
For the most popular programming languages we have set up a repository that contains samples on how to use HTTP/2 and it’s features. Use at your own risk:
We are working on enabling HTTP/2 by default for requests coming into the platform using the default domain (e.g.
some-app.cfapps.<ls>.hana.ondemand.com). This will not affect traffic from the platform to your applications since this would break many applications. We will post an update to the community after we rolled it out.