Typesafe webinar notes: Spray & Akka HTTP
Presenter - Mathias Doenitz
- embeddable http stack built on Akka actors
- Just an HTTP integration layer, not for building full web apps
- Server & client side
- Immutable case-class based http model
- Fast, lightweight http client & server
- Powerful DSL for server side API definition
- Async, non-blocking, actor-friendly, modular, testable
- Completely built in Scala (only such framework Mathias knows about)
- Chunked requests handling clunky (I would say doesn't work)
- Large messages entities can be difficult
- High-level routing DSL sometimes unintuitive, some mistakes not caught at compile time
- Deep implicit structures, sometimes hard to debug
- Missing features (notably websockets)
Akka-http is Spray 2.0
- Addresses weaknesses
- Java APIs
- Simplified module structure
- Core improvement : now based on Reactive Streams
Reactive Streams: Motivation
- A Spray proxy that is receiving a file from a fast connection (like a LAN) and sending it to a slower connection (like a WAN, internet) lacks a way to provide back pressure
- Stages in the pipeline need a way to push back (back pressure) to throttle previous, faster steps
- Pushing back up the stages just moves the problem up the pipeline. We need the problem to be moved all the way back to the beginning.
- Common solution:
ACKingworks, but is brittle, doesn't compose and isn't DRY
Reactive Streams address the problem of how to transfer data asynchronously between data producer and data consumer. Existing solutions:
- Consumer Pulls data from Producer.
- Blocking, not good for scaling
- But the blocking is minimized if producer is faster than consumer, but you can't always ensure that
- Producer Push data to Consumer whenever data becomes available
- Straight forward, good performance
- Only works reliably when consumer is faster than producer, otherwise leads to buffering
- Dynamic push/pull two step process
- Consumer signals demand (ie gie me 5 more)
- Producer Pushes elements when available, but never more than requested
- Can run in bounded memory, can increase machine utilisation since we don't need "headspace"
Now in the pipeline information flows in both directions. Signals for demand go one direction and data gets pushed the other direction. TCP semantically works in the same way and provides the back pressure.
- Pipeline processing "done right"
- Focus: define passing of data across an async boundary
- Implementations provide DSLs for composable stream transformations
- Many use cases
- Joint effort of Netflix (video streams), Twitter (tweet streams), Red Hat, Pivotal & Typesafe
Akka-stream: basic concepts
- Just one implementation of Reactive Streams
- Most complete one in Scala
Source[T]: open end of pipeline producing
Sink[T]: end-piece for consuming
Flow[A,B]: an unconnected piece of pipeline
- Generally, all abstractions are re-usable
- "Materialization" : The process of starting an actual stream instance
- So far this is not http specific. That's where Akka-http comes in.
Streams in Akka-http
- Requests on one HTTP connection
- Responses on one HTTP connectoin
- Chunks of a chunked message
- Bytes of a message entity
- For a large, unchunked message
- Setting up the Server and Client transport layers with
Flows (Akka-streams) looks a lot different from Spray
- The HttpRequest is very similar to that from Spray
- Now has a Chunked type of Http Entity
Benefits over Spray Design
- Properly typed model for requests, responses and nested entities
- Old model was a bunch of stuff crammed under one roof
- Entities can have arbitrary size
- Chunks no on an inner level, below the messages
- Can now receive message headers before the entity
- Not possible in Spray
- Steven says : this is huge for performance
Akka-http module Structure
- http model (spray-http)
- low-level stack (spray-can)
- (un)marshalling, (de)compression (spray-httpx)
- Routing DSLs (spray-routing)
- akka-http-testkit (spray-testkit)
- No more spray-servlet (for now)
- Steven says : (for now) sounds like (forever) since Play also doesn't seem to be coming back to running in a Servlet in favor of pushing the native stack
- Finalize Reactive Streams API
- Finish new akka modules
- Add websockets support (client & server side)
- Move Play onto akka-http (incrementally)
- Play wants to move to websockets, so that's necessary before moving onto Play
Q & A
- I asked about Spray-json going forward and he gave a long answer that implied it was going away. Well not really going away, but isn't going to be worked on in favor of doing something to unify all the myriad Json serliazation libraries.
- Going forward Spray will only have support releases/patches, no more major releases
- There are plans to integrate the overlap between Akka-streams and Spark. No definite plans, but Mathias is sure it will happen
- How hard is it going to be to migrate? Relatively easy. There will be a migration guide.
- Actors are lower level than streams. Streams are on the business level. There will be some interoperability such as an Actor that can act as a Source of a stream.
- Streams api will have things that aren't possible with the collections api. Example: group within 1 second. Transform streams of events into stream of list of events.
- There hasn't been any time spent on performance optimization. Right now Akka-http is a lot slower than Spray, but Mathias thinks it can be at least as fast and sees no reason why it won't be faster.
- There is https support. Right now it's just a basic version, but it is crucial and there are people working on it.
- Question about using Actors to parallelize slow stages of pipeline. Confusing answer: not a lot, depends on the application. There isn't a lot of built in stuff for that, but if you are good enough with Actors anything is possible.
- How long will Spray be maintained and supported? He thinks at least a year, but that's ultimately up to Typesafe.