Backpressure

The main feature of Kanaloa is to, as a reverse proxy, exert backpressure for a service during oversaturated traffic. Take the following example, the incoming traffic grows to 200 requests/second, while the capacity remains at 100 requests/second. Kanaloa will reject the excessive 100 requests/second and let the service handle the other 100 requests/second with optimal speed.

backpressure

Kanaloa ensures that the service under pressure works at optimal parallelity, while the optimal performance is unknown beforehand and changes over time. Kanaloa also enables control over latency caused by the queuing. For details see theories

Kanaloa can work with services as an async Function A => Future[B]

import kanaloa._
import scala.concurrent._
import scala.concurrent.duration._
import com.typesafe.config._
import scala.concurrent.ExecutionContext.Implicits.global
val cfg = ConfigFactory.parseString("akka { log-dead-letters = off }")

val proxyFactory = ReverseProxyFactory(cfg)
val service = (i: Int) => Future(i.toString)
// service: Int => scala.concurrent.Future[String] = <function1>

val proxy: Int => Future[Either[WorkException, String]] = proxyFactory(service)
// proxy: Int => scala.concurrent.Future[Either[kanaloa.WorkException,String]] = <function1>

val result = proxy(42)
// result: scala.concurrent.Future[Either[kanaloa.WorkException,String]] = List()

Await.result(result, 1.second)
// res1: Either[kanaloa.WorkException,String] = Right(42)

Kanaloa can work with services as Actor

import akka.actor.ActorDSL._
import akka.actor.ActorSystem
implicit val system = ActorSystem("demo")
val actorService = actor(new Act {
  become {
    case whateverQuestion  sender() ! "42"
  }
})
// actorService: akka.actor.ActorRef = Actor[akka://demo/user/$a#2059317969]

val actorProxy = proxyFactory[String, String](actorService)
// actorProxy: kanaloa.ReverseProxy[String,String] = <function1>

val result2 = actorProxy("what's the meaning of life?")
// result2: scala.concurrent.Future[Either[kanaloa.WorkException,String]] = List()

Await.result(result2, 1.second)
// res2: Either[kanaloa.WorkException,String] = Right(42)