Orchestration DSL
Agenda One-minute Intro to squbs
The Orchestration Use Case
Describing Orchestration in a DSL
Errors & Timeouts
Integrations
https://github.com/paypal/squbs
Standardization for Large number
of Heterogeneous Services
Hooks for Logging &
Operationalization
Programming Patterns
Internet Scale Akka
Orchestration Use-Cases
Orchestrator
Worker
Worker
Worker
Service
Service
Service
Request/Response Message
Orchestration Use-Cases
• Blocking threads while waiting for
tasks
• Highly inefficient use of resources
• Prone to downstream failures and
connection stacking
Synchronous Systems
• Message-oriented
• Never blocking
• Optimal parallelism – with Akka
Asynchronous Systems
Common pattern coordinating workers & services
Synchronous Dispatch Model
Request Thread Pool
AcceptorThread
select
n concurrent requests
n concurrent threads
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Service Calls
Request Thread Pool
Blocked
Service
Client
AcceptorThread
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Blocked
Service
Client
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Blocked
Service
Client
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Blocked
Service
Client
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Service Orchestration
Request Thread Pool
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Request Thread Pool9
Blocked
Orchestrat
e
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Blocked
Orchestrat
e
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Blocked
Orchestrat
e
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Blocked
Orchestrat
e
Worker
Logic
JAX-RS
Resource
Servlet
Catalina/
Valves
Orchestration Thread Pool
Blocked
Service
Client
Task
Blocked
Service
Client
Task
Blocked
Service
Client
Task
Blocked
Service
Client
Task
Problem
Summary
Synchronous, thread-holding
Threads blocked from useful
processing
Need for orchestrator to make parallel
service calls
Even more orchestration threads
Heavy resource usage & context switch
Akka Async, message passing middleware
Actors hold state but not threads
Low thread count, low context switch
Resilience & Supervision
Akka Actor Scheduling
12
Dispatcher
Low number of threads (1-2 per CPU)
Actor
Message Received
Run to completion
Multiple messages per dispatch
Actor Scheduled on Thread
Scheduling Actor ≠ Scheduling “task”
Asynchronous Orchestration Model
• Tasks represented by actors and/or services
• Tasks dependent on each others by results of previous task
• Each task can run independent of each other
• Tasks can run as early as the input to these tasks are available
• Tasks may or may not run parallel to other tasks, resource dependent
Before We Start
• Make sure you have the right dependency in your build.sbt
libraryDependencies += "org.squbs" %% "squbs-pattern" % "0.8.0"
Setting up the Orchestrator
class MyTaskOrchestrator(task1Actor: ActorRef, task2Actor: ActorRef,
task3Actor: ActorRef, task4Actor: ActorRef,
task5Actor: ActorRef)
extends Actor with Orchestrator {
expectOnce {
case input: Input => orchestrate(input, sender())
}
def orchestrate(input: Input, requester: ActorRef): Unit = {
// Goodies go here…
}
}
Input Dependencies
task1
task2
task3
task4
task5
Input
Output
val task1F = doTask1(input)
val task2F = doTask2(input)
val task3F = (task1F, task2F) >> doTask3
val task4F = task2F >> doTask4
val task5F = (task3F, task4F) >> doTask5
for { result <- task5F } {
requester ! result
context.stop(self)
}
Describing the Orchestration in an Actor
task1
task2
task3
task4
task5
Input
Output
Orchestrator Characteristics
• Single-use actor, terminates after ONE orchestration
• Keeps orchestration state in Actor as OFuture
• OFuture: Same API as Future, no ExecutionContext
• Runs callbacks on actor message handling thread
• Similar to Java 8 CompletableFuture synchronous API
• Spares users and actors from potential concurrent close-overs
• Future implicitly converts to OFuture in Orchestrator Actor
• Resolves final result from one or more OFutures using for-
comprehensions and sends back to requester
Orchestration Functions
• (in1: T, in2: U, … inN: W) => OFuture[X]
• Mentioned as doTask1, doTask2, etc. in the example
• Usually calls other actors
• May use ask to ask another actor
• Or better performance – tell and receive value with expectOnce
Orchestration Function Examples
def doTask1(input: Input): OFuture[Task1Output] = {
implicit val timeout = Timeout(5 seconds)
(task1Actor ? input).mapTo[Task1Output]
}
def doTask3(input1: Task1Output, input2: Task2Output):
OFuture[Task3Output] = {
val promise = OPromise[Task3Output]
task3Actor ! Task3Input(input1.s, input2.s)
expectOnce {
case o: Task3Output => promise.success(o)
case e: Task3Exception => promise.failure(e)
}
promise.future
}
Be Responsive, Do Timeout
…
val task4F = task2F >> doTask4
val task5F = (task3F, task4F) >> doTask5
for { result <- task5F } {
requester ! result
context.stop(self)
}
import context.dispatcher
context.system.scheduler.scheduleOnce(100 millis, self, Timeout)
expectOnce {
case Timeout =>
requester ! Timeout
context.stop(self)
}
And Handle Your Errors
…
expectOnce {
case Timeout =>
requester ! Timeout
context.stop(self)
}
task2F onFailure {
case e: Task2Exception =>
requester ! e
context.stop(self)
}
More Error Handling…
// Combining Futures
val myFailF =
for {
t1 <- task1F
e2 <- task4F.failed
} yield CombinedException(t1.s + e2.getMessage)
// Recovering Futures
val task3RecoveredF = task3SuccessF.recover {
case e: Task3Exception => Task3Output("It's OK")
}
Orchestration
Summary
High-performance asynchronous
orchestration
Responsive: Respond within SLA,
with or without results
Streamlined error handling
Reduced code complexity
Integrations/Usa
ge
Spray/Akka HTTP:
onComplete + ask
Akka Streams:
mapAsync + ask
Any actor:
ask or tell
As a sub-Orchestrator
when Orchestrator gets complex
Bootstrap & lifecycle control
for http, actors, and streams
Extension model for hooking into
operationalization
Data center aware clustering
Actor registry
Monitoring & console
Many more patterns
What’s more about it?
Q&A – Feedback Appreciated
Asynchronous Orchestration DSL on squbs

Asynchronous Orchestration DSL on squbs

  • 1.
  • 2.
    Agenda One-minute Introto squbs The Orchestration Use Case Describing Orchestration in a DSL Errors & Timeouts Integrations
  • 3.
    https://github.com/paypal/squbs Standardization for Largenumber of Heterogeneous Services Hooks for Logging & Operationalization Programming Patterns Internet Scale Akka
  • 4.
  • 5.
    Orchestration Use-Cases • Blockingthreads while waiting for tasks • Highly inefficient use of resources • Prone to downstream failures and connection stacking Synchronous Systems • Message-oriented • Never blocking • Optimal parallelism – with Akka Asynchronous Systems Common pattern coordinating workers & services
  • 6.
    Synchronous Dispatch Model RequestThread Pool AcceptorThread select n concurrent requests n concurrent threads Worker Logic JAX-RS Resource Servlet Catalina/ Valves Worker Logic JAX-RS Resource Servlet Catalina/ Valves Worker Logic JAX-RS Resource Servlet Catalina/ Valves Worker Logic JAX-RS Resource Servlet Catalina/ Valves
  • 7.
    Service Calls Request ThreadPool Blocked Service Client AcceptorThread Worker Logic JAX-RS Resource Servlet Catalina/ Valves Blocked Service Client Worker Logic JAX-RS Resource Servlet Catalina/ Valves Blocked Service Client Worker Logic JAX-RS Resource Servlet Catalina/ Valves Blocked Service Client Worker Logic JAX-RS Resource Servlet Catalina/ Valves
  • 8.
    Service Orchestration Request ThreadPool Worker Logic JAX-RS Resource Servlet Catalina/ Valves Worker Logic JAX-RS Resource Servlet Catalina/ Valves Worker Logic JAX-RS Resource Servlet Catalina/ Valves Worker Logic JAX-RS Resource Servlet Catalina/ Valves
  • 9.
  • 10.
    Problem Summary Synchronous, thread-holding Threads blockedfrom useful processing Need for orchestrator to make parallel service calls Even more orchestration threads Heavy resource usage & context switch
  • 11.
    Akka Async, messagepassing middleware Actors hold state but not threads Low thread count, low context switch Resilience & Supervision
  • 12.
    Akka Actor Scheduling 12 Dispatcher Lownumber of threads (1-2 per CPU) Actor Message Received Run to completion Multiple messages per dispatch Actor Scheduled on Thread Scheduling Actor ≠ Scheduling “task”
  • 13.
    Asynchronous Orchestration Model •Tasks represented by actors and/or services • Tasks dependent on each others by results of previous task • Each task can run independent of each other • Tasks can run as early as the input to these tasks are available • Tasks may or may not run parallel to other tasks, resource dependent
  • 14.
    Before We Start •Make sure you have the right dependency in your build.sbt libraryDependencies += "org.squbs" %% "squbs-pattern" % "0.8.0"
  • 15.
    Setting up theOrchestrator class MyTaskOrchestrator(task1Actor: ActorRef, task2Actor: ActorRef, task3Actor: ActorRef, task4Actor: ActorRef, task5Actor: ActorRef) extends Actor with Orchestrator { expectOnce { case input: Input => orchestrate(input, sender()) } def orchestrate(input: Input, requester: ActorRef): Unit = { // Goodies go here… } }
  • 16.
  • 17.
    val task1F =doTask1(input) val task2F = doTask2(input) val task3F = (task1F, task2F) >> doTask3 val task4F = task2F >> doTask4 val task5F = (task3F, task4F) >> doTask5 for { result <- task5F } { requester ! result context.stop(self) } Describing the Orchestration in an Actor task1 task2 task3 task4 task5 Input Output
  • 18.
    Orchestrator Characteristics • Single-useactor, terminates after ONE orchestration • Keeps orchestration state in Actor as OFuture • OFuture: Same API as Future, no ExecutionContext • Runs callbacks on actor message handling thread • Similar to Java 8 CompletableFuture synchronous API • Spares users and actors from potential concurrent close-overs • Future implicitly converts to OFuture in Orchestrator Actor • Resolves final result from one or more OFutures using for- comprehensions and sends back to requester
  • 19.
    Orchestration Functions • (in1:T, in2: U, … inN: W) => OFuture[X] • Mentioned as doTask1, doTask2, etc. in the example • Usually calls other actors • May use ask to ask another actor • Or better performance – tell and receive value with expectOnce
  • 20.
    Orchestration Function Examples defdoTask1(input: Input): OFuture[Task1Output] = { implicit val timeout = Timeout(5 seconds) (task1Actor ? input).mapTo[Task1Output] } def doTask3(input1: Task1Output, input2: Task2Output): OFuture[Task3Output] = { val promise = OPromise[Task3Output] task3Actor ! Task3Input(input1.s, input2.s) expectOnce { case o: Task3Output => promise.success(o) case e: Task3Exception => promise.failure(e) } promise.future }
  • 21.
    Be Responsive, DoTimeout … val task4F = task2F >> doTask4 val task5F = (task3F, task4F) >> doTask5 for { result <- task5F } { requester ! result context.stop(self) } import context.dispatcher context.system.scheduler.scheduleOnce(100 millis, self, Timeout) expectOnce { case Timeout => requester ! Timeout context.stop(self) }
  • 22.
    And Handle YourErrors … expectOnce { case Timeout => requester ! Timeout context.stop(self) } task2F onFailure { case e: Task2Exception => requester ! e context.stop(self) }
  • 23.
    More Error Handling… //Combining Futures val myFailF = for { t1 <- task1F e2 <- task4F.failed } yield CombinedException(t1.s + e2.getMessage) // Recovering Futures val task3RecoveredF = task3SuccessF.recover { case e: Task3Exception => Task3Output("It's OK") }
  • 24.
    Orchestration Summary High-performance asynchronous orchestration Responsive: Respondwithin SLA, with or without results Streamlined error handling Reduced code complexity
  • 25.
    Integrations/Usa ge Spray/Akka HTTP: onComplete +ask Akka Streams: mapAsync + ask Any actor: ask or tell As a sub-Orchestrator when Orchestrator gets complex
  • 26.
    Bootstrap & lifecyclecontrol for http, actors, and streams Extension model for hooking into operationalization Data center aware clustering Actor registry Monitoring & console Many more patterns What’s more about it?
  • 27.
    Q&A – FeedbackAppreciated