Anatomy of an Actor (akka)
- Internally single threaded - easy to reason
- Actor systems - nice concurrency model
- Resource allocation (threads) in config at runtime
- Mailbox - be careful - unbounded - out of memory
... but wait
What can we do about the mail box out of memory
How can we create back pressureWhy is it hard?
Non-blocking back pressure is hard. It gets even harder when considering remote workers
Java8 Streams
- Eager evaluation - forEach :(
- Static push or pull :(
- Cannot reuse streams :(
RxJava
- Back pressure by blocking :(
- No back pressure for remote workers :(
- Push only :(
pull <-----> push
- Push - to workers
- Pull - from coordinator
- Choose one or both?
Work Pulling Pattern - both
- Pull - when the coordinator has lots of work to do
- Push - when the workers have more capacity than the coordinator
Reactive Streams Goal
- A standard for asynchronous stream processing with non-blocking back pressure on the JVM
- Cool = Interop with RxJava, Vertx, Akka etc
Simple Interface
trait Publisher[T] {
def subscribe(sub: Subscriber[T]): Unit
}
triat Subscription {
def requestMore(n: Int): Unit
def cancel(): Unit
}
trait Subscriber[T] {
def onSubscribe(s: Subscription): Unit
def onNext(elem: T): Unit
def onError(thr: Throwable): Unit
def onComplete(): Unit
}
Examples
- Data transfer
- Real-time data processing - stock market
- Batch processing - spark
- Monitoring - analytics
Akka Reactive Streams
- Implementation of the work pulling pattern
- All the complexity is hidden
- Non blocking back pressure :)
- Dynamic pull / push :)
- Statically Typed :)
- Remotable back pressure :)
- Reusable :)
Reactive Streams also added:
Batching for performance - CPU caching