Subactor(worker)仍然在Java Akka中的主要演员Timeout之后工作

时间:2014-12-05 23:33:56

标签: akka

我已经使用Java在Akka框架中实现了一个应用程序。我有一个主要的actor通过使用'Ask'方法调用sub-actor并在60秒后超时,worker在收到来自Main Actor的消息后调用另一个java类方法。

现在的问题是,虽然我的主演员在60秒后超时仍然工作人员能够与java类方法交谈,然后该方法正在执行不需要的操作,因为主要演员无法接收响应虽然子actor由于超时而返回。

如果主要演员超时,我是否可以杀死工作人员或阻止其进一步处理? 我检查了RecieveTimeOut()context.stop()和poisonpill等方法,但仍无用。

感谢您的支持

以下代码

public class MainActor extends UntypedActor {

    ActorRef subActorRef;

    final Timeout timeout = new Timeout(Duration.create(60, TimeUnit.SECONDS));

    @Override
    public void preStart() {
        subActorRef = getContext().actorOf(
            SpringExtProvider.get(actorSystem).props(
                "SubActor"), "subActor");
    }

    @Override
    public void onReceive(Object message) throws Exception {

        if (message instanceof BusinessRequestVO) {
            BusinessRequestVO requestVo = (BusinessRequestVO) message;
            ArrayList<Future<Object>> responseFutures = new ArrayList<Future<Object>>();

            // This part of code timeout after 60seconds
            responseFutures.add(ask(subActorRef,requestVo, timeout));
        }
    }
}

SubActor类

public class SubActor extends UntypedActor {

    @Resource
    @Inject
    ServiceAdapter serviceAdapter;

    @Override
    public void onReceive(Object message) throws Exception {
        try{
            if (message instanceof BusinessRequestVO) {
                BusinessRequestVO requestVo = (BusinessRequestVO)message

                // There is no time out here so it waits synchronously
                // though Main actor timeouts
                ServiceResponse response = serviceAdapter.getWorkOrder(requestVo);

                getSender().tell(response, ActorRef.noSender());
            } catch (Exception e) {
                getSender().tell(new akka.actor.Status.Failure(e), getSelf());
                throw e;
            }
        }
    }
}

适配器类

public class ServiceAdapterImpl implements ServiceAdapter{
    public ServiceResponse getWorkOrder(BusinessRequestVO request){
        // Some code here along with webservice calls
    }
}

1 个答案:

答案 0 :(得分:0)

你不能像你的孩子一样阻止,因此不能处理任何&#34;停止&#34;父发送给他的消息(演员在读取邮箱中的下一个消息之前一次处理一条消息)。

你最好的选择是包裹&#34;慢&#34;孩子在未来内部执行的一部分,你可以将其传递给父母(详见here)。

通过这种方式,如果您的超时到期,您可以让父母发送自定义&#34;停止计算&#34;消息,并且子actor可以终止未来。请参阅here,了解如何终止未来。

但这可能会引入&#34;脏&#34;根据在执行过程中途终止的特定计算,在应用程序逻辑中声明。

在相关的说明中:为什么要将所有n个请求发送给同一个子actor(你阻止了)?这相当于顺序执行。您应该使子actor非阻塞或(更好)为每个请求创建一个阻塞actor。

编辑:根据OP的要求,添加了片段。它是混合scala和java的伪代码,因为我不是Java语法的超级专家,我主要在Scala中使用它,所以请稍微调整一下:

if (message instanceof BusinessRequestVO) {
  new Future (
    BusinessRequestVO requestVo = (BusinessRequestVO)message
    try {
      ServiceResponse response = serviceAdapter.getWorkOrder(requestVo);
      getSender().tell(response, ActorRef.noSender());
    } 
    catch (Exception e) {
      getSender().tell(new akka.actor.Status.Failure(e), getSelf());
      throw e;
    }
  ) pipeTo sender
}

在main中(请参阅here了解java的future.cancel)

if (timeout) future.cancel(true)