akka balance router的实现

当akka处于balance策略的时候,Akka的父actor在选择相应的子actor去执行相应的消息时,不会直接直接选择,而是在分发器dispatch中,通过共享邮箱的方式,选择一个空闲的子actor去执行这个消息。

 

具体的balance策略BalanceRoutingLogic的apply方法只是返回了所有子actor的第一个,并没有执行具体的选择操作。

private[akka] object BalancingRoutingLogic {
  def apply(): BalancingRoutingLogic = new BalancingRoutingLogic
}

但是,在balance对应的RouterPool的BalancePool则实现了自己的newRoutee()方法,在这个方法中,给actor对应的分发器设置了BalancingDispatcherConfigurator,使得具体的分发器变成了BalancingDispatcher,并建立了actor与分发器的绑定关系。

override private[akka] def newRoutee(routeeProps: Props, context: ActorContext): Routee = {

  val rawDeployPath = context.self.path.elements.drop(1).mkString("/", "/", "")
  val deployPath = BalancingPoolDeploy.invalidConfigKeyChars.foldLeft(rawDeployPath) { (replaced, c) =>
    replaced.replace(c, '_')
  }
  val dispatcherId = s"BalancingPool-$deployPath"
  def dispatchers = context.system.dispatchers

  if (!dispatchers.hasDispatcher(dispatcherId)) {
    // dynamically create the config and register the dispatcher configurator for the
    // dispatcher of this pool
    val deployDispatcherConfigPath = s"akka.actor.deployment.$deployPath.pool-dispatcher"
    val systemConfig = context.system.settings.config
    val dispatcherConfig = context.system.dispatchers.config(
      dispatcherId,
      // use the user defined 'pool-dispatcher' config as fallback, if any
      if (systemConfig.hasPath(deployDispatcherConfigPath))
        systemConfig.getConfig(deployDispatcherConfigPath)
      else ConfigFactory.empty)

    dispatchers.registerConfigurator(
      dispatcherId,
      new BalancingDispatcherConfigurator(dispatcherConfig, dispatchers.prerequisites))
  }

  val routeePropsWithDispatcher = routeeProps.withDispatcher(dispatcherId)
  ActorRefRoutee(context.actorOf(routeePropsWithDispatcher))
}

在具体执行平衡逻辑的BalancingDispathcer中,在其dispatch()方法中实现了平衡的目的。

override protected[akka] def dispatch(receiver: ActorCell, invocation: Envelope) = {
  messageQueue.enqueue(receiver.self, invocation)
  if (!registerForExecution(receiver.mailbox, false, false)) teamWork()
}

protected def teamWork(): Unit =
  if (attemptTeamWork) {
    @tailrec def scheduleOne(i: Iterator[ActorCell] = team.iterator): Unit =
      if (messageQueue.hasMessages
          && i.hasNext
          && (executorService.executor match {
            case lm: LoadMetrics => lm.atFullThrottle == false
            case _               => true
          })
          && !registerForExecution(i.next.mailbox, false, false))
        scheduleOne(i)

    scheduleOne()
  }

在BalancingDispathcer中,所有共享邮箱的actor都会保存在team中,当第一次的actor也就刚才的第一个actor进入,将会直接被消息分配给它,但是如果第二条消息进来,之前的actor如果还没有处理完毕,将会选取team中的下一个空闲的actor进行分配,达到平衡到空闲actor的目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值