设计Akka Supervisor层次结构

时间:2015-06-16 01:28:11

标签: java akka actor supervisor fault-tolerance

请注意:我是一名Java开发人员,不熟悉Scala(遗憾的是)。我会问答案中提供的任何代码示例都将使用Akka的Java API。

我是Akka和演员的新品牌,我正试图建立一个相当简单的演员系统:

enter image description here

因此,一个DataSplitter actor运行并将相当大的二进制数据块(例如20GB)拆分为100 KB块。对于每个块,数据通过DataCache存储在DataCacher中。在后台,DataCacheCleaner通过缓存搜索并找到可以安全删除的数据块。这就是我们阻止缓存大小变为20GB的方法。

将块发送到DataCacher进行缓存后,DataSplitter会通知ProcessorPool现在需要处理的块。 ProcessorPool是一个路由器/池,由数万的不同ProcessorActors组成。当每个ProcessActor收到通知"进程"一个100KB的数据块然后从DataCacher获取数据并对其进行一些处理。

如果您想知道为什么我在这里缓解任何问题(因此DataCacherDataCacheDataCacheCleaner),我的思考是100KB仍然是一个相当大的消息传递给成千上万的actor实例(100KB * 1,000 = 100MB),所以我试图只存储一次100KB的块(在缓存中),然后让每个actor访问它通过缓存API引用。

还有一个Mailman演员订阅了活动总线并拦截了所有DeadLetters

所以,共有6位演员:

  • DataSplitter
  • DataCacher
  • DataCacheCleaner
  • ProcessorPool
  • ProcessorActor
  • Mailman

Akka文档宣称你应该根据子任务而不是纯粹按功能来分解你的演员系统,但我并不完全看到这在这里是如何适用的。手头的问题是我试图在这些演员之间组织一个主管层级,而我不确定最佳/正确的方法是什么。显然ProcessorPool是一个需要成为ProcessorActors的父/主管的路由器,所以我们有这个已知的层次结构:

/user/processorPool/
    processorActors

但除了已知/明显的关系之外,我不确定如何组织其余的演员。我可以让他们所有人#34;同行"在一位共同/主要演员的指导下:

/user/master/
    dataSplitter/
    dataCacher/
    dataCacheCleaner/
    processorPool/
        processorActors/
    mailman/

或者我可以省略master(root)actor并尝试在缓存周围使事情更加垂直:

/user/
    dataSplitter/
    cacheSupervisor/
        dataCacher/
        dataCacheCleaner/
    processorPool/
        processorActors/
    mailman/

对阿卡来说是个新人我不知道最好的行动方案是什么,如果有人可以帮助我在这里进行一些初步的手持操作,我确定灯泡会全部打开。而且,与组织此层次结构同样重要的是,我甚至不确定我可以使用什么API构造来实际在代码中创建层次结构。

1 个答案:

答案 0 :(得分:0)

在一个master下组织它们会使管理变得更容易,因为您可以通过主管(在这种情况下watched)访问所有参与者master

一个分层实现可以是:

硕士生导师

class MasterSupervisor extends UntypedActor {

private static SupervisorStrategy strategy = new AllForOneStrategy(2,
        Duration.create(5, TimeUnit.MINUTES),

        new Function<Throwable, Directive>() {
            @Override
            public Directive apply(Throwable t) {

                if (t instanceof SQLException) {
                    log.error("Error: SQLException")
                    return restart()
                } else if (t instanceof IllegalArgumentException) {
                    log.error("Error: IllegalArgumentException")
                    return stop()
                } else {
                    log.error("Error: GeneralException")
                    return stop()
                }
            }
        });

@Override
public SupervisorStrategy supervisorStrategy() { return strategy }

@Override
void onReceive(Object message) throws Exception {
     if (message.equals("SPLIT")) {
          // CREATE A CHILD OF MyOtherSupervisor
          if (!dataSplitter) {
              dataSplitter = context().actorOf(FromConfig.getInstance().props(Props.create(DataSplitter.class)), "DataSplitter")

              // WATCH THE CHILD
              context().watch(dataSplitter)

              log.info("${self().path()} has created, watching and sent JobId = ${message} message to DataSplitter")
          }

          // do something with message such as Forward
          dataSplitter.forward(message, context())
      }
}

DataSplitter Actor

class DataSplitter extends UntypedActor {

    // Inject a Service to do the main operation
    DataSplitterService dataSplitterService

    @Override
    void onReceive(Object message) throws Exception {
        if (message.equals("SPLIT")) {
            log.info("${self().path()} recieved message: ${message} from ${sender()}")
            // do something with message such as Forward
            dataSplitterService.splitData()
        }
    }
}