Router configurations and strategies for distributing messages across multiple actor instances for load balancing and fault tolerance.
Base router configuration and types for message distribution.
/**
* Abstract base class for router configurations
*/
abstract class RouterConfig {
def createRouter(system: ActorSystem): Router
def routerDispatcher: String
def stopRouterWhenAllRouteesRemoved: Boolean
}
/**
* No routing configuration
*/
case object NoRouter extends RouterConfig
/**
* Pool-based routing (router creates and manages routees)
*/
abstract class Pool extends RouterConfig {
def nrOfInstances: Int
def resizer: Option[Resizer]
def supervisorStrategy: SupervisorStrategy
}
/**
* Group-based routing (router uses existing actors as routees)
*/
abstract class Group extends RouterConfig {
def paths: immutable.Iterable[String]
def routerDispatcher: String
}Various routing algorithms for message distribution.
// Round-robin routing
class RoundRobinPool(nrOfInstances: Int) extends Pool
class RoundRobinGroup(paths: immutable.Iterable[String]) extends Group
// Random routing
class RandomPool(nrOfInstances: Int) extends Pool
class RandomGroup(paths: immutable.Iterable[String]) extends Group
// Smallest mailbox routing
class SmallestMailboxPool(nrOfInstances: Int) extends Pool
// Broadcast routing
class BroadcastPool(nrOfInstances: Int) extends Pool
class BroadcastGroup(paths: immutable.Iterable[String]) extends Group
// Balancing routing
class BalancingPool(nrOfInstances: Int) extends Pool
// Consistent hashing routing
class ConsistentHashingPool(nrOfInstances: Int) extends Pool
class ConsistentHashingGroup(paths: immutable.Iterable[String]) extends GroupUsage Examples:
import akka.actor.{ActorSystem, Props}
import akka.routing._
val system = ActorSystem("RoutingExample")
// Round-robin pool with 5 instances
val roundRobinRouter = system.actorOf(
Props[WorkerActor]().withRouter(RoundRobinPool(5)),
"round-robin-router"
)
// Random pool with auto-scaling
val randomRouter = system.actorOf(
Props[WorkerActor]().withRouter(
RandomPool(5).withResizer(DefaultResizer(lowerBound = 2, upperBound = 15))
),
"random-router"
)
// Send messages - will be distributed across routees
for (i <- 1 to 10) {
roundRobinRouter ! s"Message $i"
}Core router implementation and routee management.
/**
* Router implementation managing routees and message distribution
*/
class Router(val logic: RoutingLogic, val routees: immutable.IndexedSeq[Routee] = Vector.empty) {
def route(message: Any, sender: ActorRef): Unit
def addRoutee(routee: Routee): Router
def removeRoutee(routee: Routee): Router
def withRoutees(rs: immutable.IndexedSeq[Routee]): Router
}
/**
* Routee abstractions
*/
trait Routee {
def send(message: Any, sender: ActorRef): Unit
}
case class ActorRefRoutee(ref: ActorRef) extends Routee
case class ActorSelectionRoutee(selection: ActorSelection) extends Routee
/**
* Routing logic algorithms
*/
abstract class RoutingLogic {
def select(message: Any, routees: immutable.IndexedSeq[Routee]): Routee
}Dynamic resizing of router pools based on load and performance metrics.
/**
* Abstract resizer for dynamic pool sizing
*/
abstract class Resizer {
def isTimeForResize(messageCounter: Long): Boolean
def resize(currentRoutees: immutable.IndexedSeq[Routee]): Int
}
/**
* Default resizer with configurable bounds
*/
class DefaultResizer(
lowerBound: Int = 1,
upperBound: Int = 10,
pressureThreshold: Int = 1,
rampupRate: Double = 0.2,
backoffThreshold: Double = 0.3,
backoffRate: Double = 0.1,
messagesPerResize: Int = 10
) extends Resizer