Dropwizard 1.3 Upcoming TLS Improvements

No longer is Dropwizard’s performance hobbled by Java’s TLS implementation

In Dropwizard 1.3, you could see a 10x improvement in latency reduction with services that deal with large payloads (either in the response or request). There’s a lot that went behind this effort, so let’s break it down. See the example code on dropwizard-tls-benchmark repo.

Reference Solution

Get the benefits by modifying your pom.xml

<dependency>
    <groupId>org.conscrypt</groupId>
    <artifactId>conscrypt-openjdk-uber</artifactId>
    <version>${conscrypt.version}</version>
</dependency>

Then in your server or client config:

applicationConnectors:
 - type: https
   jceProvider: Conscrypt

Introduction

In the post the Cost of TLS in Java, I showed that while TLS (oftentimes written SSL/TLS, but I’ll stick with TLS) has been optimized to the point that performance impacts are neglible in nearly all web servers like nginx, apache, IIS. The same can’t be said for Java projects using the built in TLS implementation. The team behind the Java webserver Jetty, recommended to put a TLS terminator in front of the server when performance mattered. I felt like that introduced too much complexity for small deployments so I couldn’t wholeheartedly recommend that approach. Everything has changed.

  • Netty and Tomcat (two Java projects) saw the need for a better TLS implementation and so offered bindings into OpenSSL.
  • This wasn’t a generic solution, so Google was inspired to release Conscrypt, which hooks into BoringSSL for performance.
  • Jetty took notice and created integrations for Conscrypt
  • Dropwizard saw the improvements in Jetty and upgraded to the latest version for 1.3 so that end users can benefit.

Improvements

No more modifying bootpath

For Dropwizard HTTP2 (h2), modifying the boot classpath is a major pain. Java 8 doesn’t support Application-Layer Protocol Negotiation (ALPN) required for h2, so users would have to track down the correct ALPN jar. This jar changes with every Java 8 update, and there has been a few dozen of those. As an example, someone would have to add -Xbootclasspath/p:alpn-boot-8.1.11.v20170118.jar for 8u151 to start their server. The operational team couldn’t update Java on the server as that would break the application.

No more worries, simply add to your pom:

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-alpn-conscrypt-server</artifactId>
</dependency>

Conscrypt removes any reason to modify the boot classpath, as it provides an ALPN implementation that is JRE independent.

Performance Improvements

To test the performance of a service using Conscrypt, I wrote an echo server, which echoes the request body as the response body. It ignores headers like Content-Type, but that shouldn’t be an issue as reading and writing the body should be most the cost.

@Path("/")
public class EchoResource {
    @POST
    public StreamingOutput echo(InputStream in) {
        return output -> ByteStreams.copy(in, output);
    }
}

I also wrote an endpoint that eschewed Jersey for a servlet. In Turning Performance to Eleven, we saw that Jersey does have a performance cost, and I wanted to see how that cost carries over to TLS improvements.

public class EchoServlet extends HttpServlet {                                  
    @Override                                                                   
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setStatus(HttpServletResponse.SC_OK);                              
        ByteStreams.copy(req.getInputStream(), resp.getOutputStream());         
    }                                                                           
}

Using h2load to benchmark both HTTPS 1.1 and 2.0, we will measure a percentage improvement in the number of requests served per second when we vary the request body size from 1 to 100KB.

In the top graph we see a 100KB payload is delivered 7.5x faster when using Conscrypt in our Jersey HTTP2 echo endpoint (10x for servlet). There was also improvement in HTTPS 1.1 endpoint of nearly 2.5x, which still impressive. For smaller payloads there is not a tangible speedup (I realize to test TLS negotiation and initialization I’d want my load testing tool to not reuse connections).

Conclusion

When Dropwizard 1.3 comes out, I advocate for everyone to give a try. I’m confident that the implementation is sound, but the more people testing and using Conscrypt will move the TLS laggards who are still smarting from poor performance of Java’s default TLS implementation.

Even if performance is not concern for h2 services, one should still leverage Conscrypt for ease in deployments.

If you would like to take a look at example code using Conscrypt and the benchmark harness, check out the dropwizard-tls-benchmark repo.

Comments: