具有Akka和长时间运行进程的actor模式

时间:2015-11-13 20:40:16

标签: java scala akka actor

最近,我一直在调查令人敬畏的Akka框架,试图了解它并决定它是否适合我的项目。目前,这个应用程序是一个普通的旧java应用程序,它通过调用各种外部c ++可执行文件来执行一些非常复杂的计算(有时计算可能需要数小时才能运行)。在代码中它看起来像这样

public static class Worker extends UntypedActor {
  // Run Very Long Process 
  public void onReceive(Object message) {
    if (message instanceof Work) {
        Work work = (Work) message;
        double result = veryLongProcess(work.getStart(),work.getNrOfElements());
        getSender().tell(new Result(result), getSelf());
    } else {
       unhandled(message);
    }
  }
}

我的问题是,Akka可以处理演员有时需要几个小时才能从执行中返回吗?

2 个答案:

答案 0 :(得分:2)

直接回答你的问题;在这个主题上有一个good article

  

同样,如果你有长时间运行的计算,让它们运行在   单独的ExecutionContext用于CPU绑定任务是一个好主意。

该文章有以下示例:

import java.util.concurrent.Executors
import concurrent.ExecutionContext

//I added 'private' for the rest of the example
private val executorService = Executors.newFixedThreadPool(4)
private val executionContext = ExecutionContext.fromExecutorService(executorService)

间接回答,

期货优先

我完全同意Akka Actors对于特定类型的工作是非常有用的工具。谈到缓存,Actors& Agents是镇上最好的游戏。

但是,在这种情况下,我建议利用Future而不是演员。您可以使veryLongProcess成为private函数。隐私将允许完全控制一次调用该方法的线程数:

def longProcessFut(start : Int, noOfElements : Int) : Future[Result] = Future {
  veryLongProcess(start, noOfElements)
}(executionContext)//controls the executing pool of veryLongProcess

简单,简洁,异步。

没有杀死字母,没有重载的接收方法接受任何阳光下的东西,也没有Props,甚至连ActorRef都不是Future的必需品。膨胀,啤酒肚我说!

此外,由于?

,您的用户无论如何都会创建未来
//Actor user code, too verbose

val longProcessRef = actorSystem actorOf Props[Worker]

val fut : Future[Result] = (longProcessRef ? Work(0,42)).mapTo[Result]

与直接使用期货相比

//happy user code

val fut : Future[Result] = longProcessFut(0, 42)

同样伟大的未来,但卡路里的一半!

您可以按照评论中建议的相同方式控制Future的调度员,这非常好。您甚至可以使用actorSystem.dispatcher作为Future调度程序来控制调度程序行为。

答案 1 :(得分:0)

如果长时间运行的业务逻辑/算法是增量式的,产生中间结果和/或可以长时间非常运行,那么您可能希望从这里重用优秀的设计片段:{{3} }