Akka HTTP 10.2 Release - Q/A with the Akka team
We recently sat down with Johannes Rudolph, Senior Engineer on the Akka Platform team at Lightbend, to discuss the recent launch of Akka HTTP 10.2, which includes various improvements based on Akka 2.6, a reduction in boilerplate code for Java developers, and improved interop with Akka gRPC.
What were the major improvements?
Akka HTTP 10.2.0 builds on top of the improvements of Akka 2.6 and now works seamlessly with both typed and classic ActorSystems. One major improvement of Akka 2.6 was that Akka Stream Materializers are often not needed any more. We jumped on that train and simplified Akka HTTP’s APIs to avoid passing Materializers where possible.
If you had to pick the most significant update in this release, what would it be?
The most user-visible change is that we introduced a new ServerBuilder API for binding servers. The need arose as a consequence of evolving the main entry points to work without Materializers. Especially, on the Java-side, a lot less boilerplate is required now to bind a server.
Here is a Java example for how things worked with 10.1.x:
// only worked with classic actor system akka.actor.ActorSystem system = akka.actor.ActorSystem.create("TheSystem"); Materializer mat = ActorMaterializer.create(system); Route route = get(() -> complete("Hello World!")); Http.get(system).bindAndHandle(route.flow(system), ConnectHttp.toHost("localhost", 8080), mat);
Previously, you could only use classic ActorSystems or had to convert the typed ActorSystem to a classic one manually. Then you had to create a materializer for running the binding. Finally, a route had to be converted into a flow before passing it into
bindAndHandle and the binding address had to be specified verbosely using
Here’s is how it looks today with 10.2.0:
akka.actor.typed.ActorSystem system = akka.actor.typed.ActorSystem.create(Behaviors.empty(), "TheSystem"); Route route = get(() -> complete("Hello World!")); Http.get(system).newServerAt("localhost", 8080).bind(route);
All the non-essential boilerplate is gone and the binding is created in a straight-forward way using the
newServerAt API new in 10.2.0.
That aside, we made a lot of improvements in the details. Look at the list of changes, there were improvements in many areas. Attributes were introduced to simplify attaching metadata to requests and responses, the client can be configured per target host, there were some performance improvements, and we prepared the codebase for the future by changing some defaults and letting users to avoid code patterns that will not be supported in Scala 3.
What was the biggest challenge in this release?
We decided to keep full compatibility with Akka 2.5 for this release. We all know the dreaded dependency treadmill where updating one dependency can trigger a whole chain of other updates. Seemingly small updates grow in size and impact and developers might delay important updates in fear of breaking working code with big updates. Going the extra step and keeping compatibility a little while longer, will enable developers to update Akka and Akka HTTP incrementally and independently of each other.
To make that work, we went quite a long way to ensure Akka HTTP 10.2.0 continues to work on top of Akka 2.5 by backporting features from Akka 2.6 to the latest versions of Akka 2.5 to keep compatibility. This will be the last release line supporting Akka 2.5.
What was the biggest bug that feels good to have finally squashed?
We finally fixed a long-standing bug related to a race condition while propagating errors that plagued many areas of streaming usage. The details are going to be a bit technical, so bear with me. As you know, Akka HTTP builds on top of Akka Streams. For implementing protocols, it has the nice property that you can model the protocol implementation as a stack of bidirectional streaming components similar to the OSI reference model.
So, the stack for an HTTP server has at the bottom TCP, then the TLS implementation, then parsing and rendering to an intermediate representation, then a controller that manages the connection state, and a layer that assembles and disassembles the Scala request and response model. At the top is the user handler that handles a request and produces a response which ties the loop. In fact, in the code the stack is really represented like this: “... preparation atop controller atop parsingRendering atop TLS atop TCP”.
The problem with this structure is that two layers of the stack are always connected twice, once up and once down and those connections are asynchronous by nature. So, when an error occurs at some layer it will be communicated to other layers on two paths, one up and one down. Depending on which path the error was communicated more quickly, there was slightly different behavior. A common problematic behavior was that errors could be converted to regular stream completion like this, leading to subtle surprises that could sometimes be observed even on the client side.
What other Lightbend technologies does this release influence?
We recently released Akka gRPC 1.0, which builds on top of Akka HTTP’s HTTP/2 support. The 10.2.0 version introduces a new set of directives–handle and handleSync–which lets us integrate service handlers generated by Akka gRPC seamlessly with other Akka HTTP routes in your application. Also, under the hood, Akka gRPC’s use of HTTP/2 drove some improvements to the HTTP/2 implementation.
We now offer a comparison with Play routes and a style-guide to help developers coming from more traditional web frameworks with setting up a route structure. Akka HTTP’s routing DSL is a blessing and a curse in that regard. It comes with great power and flexibility but it can be hard to wrap your head around it and organize your code to scale it when your application grows. These new documentation pages are another step in getting people up to speed.
In general, Akka HTTP 10.2 is binary compatible with 10.1, so mixing it with any Lightbend or third party libraries that depend on it should work out of the box. As always, make sure that all submodules of Akka HTTP are on the same version.
What does the future roadmap look like for the next release, how can folks contribute?
We are still winding down from a busy release time, so no definite plans have been made in what’s coming next concretely. We hope to tackle the task of providing HTTP/2 client support, which would help Akka gRPC and improvements to the WebSocket and client APIs but nothing is yet set in stone.
If you want to help we are always open to contributions. For this release we had some great contributions, e.g. the per-target-host configuration option for the clients were initially contributed a long while ago and finally made it into this release. If you do not want to risk such a long turnaround time, try a ticket marked as “hackathon” for some smaller-sized contribution opportunities. But we are also happy about any kind of feedback and questions on our forum at https://discuss.akka.io.
If you're looking to explore more with Akka HTTP, Akka Streams, Akka Cluster and other parts of Akka Platform, then schedule a meeting with one of our experts to discuss the way forward!