Akka群集-从崩溃的角色中恢复数据

时间:2018-08-15 19:25:45

标签: scala akka akka-cluster

假设我有一个具有 n 个从属设备的主设备,这些从属设备位于其他计算机上。

主要演员的样子

class MasterActor extends Actor {

  val router: ActorRef = // ... initialized router to contact the slaves

  override def receive: Receive = {
    case work: DoWork => router ! work
  }
}

我的奴隶看起来像

class SlaveActor extends Actor {

  override def receive: Receive = {
    case work: DoWork => // Some logic that takes a couple of seconds
  }
}

如果托管有一些从服务器的计算机崩溃,或者如果应用在处理某些work时已停止,则我希望使用一个后备机制使系统(我想是主机)能够知道失败,然后将丢失 work重新分配给其他从属。

我已经了解了Akka中的监督原理,该原理使主演员可以在子演员无法访问时得到通知,但是我如何才能获得work的特定实例,即演员必须重新分配它呢? / p>

在我最近开始使用Akka时,我的方法可能不适合最佳实践,应该以其他方式解决这种情况吗?

谢谢!

3 个答案:

答案 0 :(得分:0)

现在,这种方法并不适用于所有情况,但是如何将子actor的工作存储到文件系统中。您可以创建一个为每个孩子提供的ID,并将作品保存在基于key -> value对的文件中,其中,孩子演员ID是键,值是进行中的作品。

现在,必须决定要保存哪些数据,但这是您可以尝试的最简单方法之一。

希望这会有所帮助!

答案 1 :(得分:0)

听起来您想要的是Akka Persistence。主要模型是事件源

一个粗略的概述是在收到DoWork时保留一个事件,并在完成工作时保留第二个事件。在恢复时,状态是未完成的工作清单(如果您正确地执行了协议,则该工作清单最多将是一项工作),具体如下:

case class DidWork(dw: DoWork)

class SlaveActor extends PersistentActor {
  val persistenceId: String = ???
  var workToDo: List[DoWork] = Nil

  val receiveRecover: Receive = {
    case dw: DoWork => workToDo = dw :: workToDo
    case DidWork(dw: DoWork) => workToDo = workToDo.filter(_ != dw)
    case SnapshotOffer(_, snapshot: List[DoWork]) => workToDo = snapshot
  }

  val snapshotInterval = ???

  val receiveCommand: Receive = {
    case dw: DoWork =>
      persist(dw) { event =>
        workToDo = dw :: workToDo
        context.system.eventStream.publish(event)
        if (lastSequenceNr % snapshotInterval == 0 && lastSequenceNr != 0)
          saveSnapshot(workToDo)

        doWork
      }
  }

  private[this] def doWork: Unit = {
    workToDo.reverse.foreach { dw: DoWork =>
      // do the work
      persist(DidWork(dw)) { event =>
        workToDo = workToDo.tail
        context.system.eventStream.publish(event)
        if (lastSequenceNr % snapshotInterval == 0 && lastSequenceNr != 0)
          saveSnapshot(workToDo)
      }
    }
  }
}

答案 2 :(得分:0)

如果您想确保主人知道要离开的工人,您可以watch(见文档https://doc.akka.io/docs/akka/current/actors.html#lifecycle-monitoring-aka-deathwatch)。如果您跟踪分配给哪些工作人员的工作量(尚未完成),则可以实施重新发送。但是,您可能必须考虑主机或其角色系统也消失的情况,以及在发生这种情况时如何恢复。

Akka分布式工作人员样本恰好涵盖了这一点,因此它可能是一个很好的灵感来源:https://developer.lightbend.com/guides/akka-distributed-workers-scala/