Akka演员的大胆策略

时间:2015-06-22 10:18:34

标签: java asynchronous akka blocking future

我有一个场景,一个重要的演员需要拨打一个缓慢的(15 - 20 )远程系统:

// Non-actor code equivalent
public Result makeSlowNetworkCall(Request request) {
    Result result = slowServiceClient.soooooSlow(request);      // Could be up to 15 - 20 SECONDS (mehhhh)
    return result;
}

与此相当的Akka 目前看起来像:

// Groovy
class SlowServiceActor extends UntypedActor {
    @Override
    void onReceive(Object message) {
        if(message instanceof CallSlowService) {
            Request request = (message as CallSlowService).request
            Result result = makeSlowNetworkCall(request)
            // ...now do something with result, some 15 seconds later
        }
    }

    Result makeSlowNetworkCall(Request request) {
        slowServiceClient.soooooSlow(request)
    }
}

显然这是阻塞,坏,坏,坏。阅读this excellent article on handling non-blocking DB calls后,我的主要内容是基本上有两个" 批量"我可以采用的策略:

  • 将所有SlowServiceActor个实例放在他们自己的调度程序中,以将其延迟/阻塞与其他不与Slow Service直接交互的actor / threads隔离开来;和
  • 通过Futures通过{" asynchronicity "
  • 调用慢速服务

所以到目前为止我最好的尝试是:

// In application.conf:
slowServiceDispatcher {
    ...config here
}

class CallSlowService implements Callable<Result> {
    @Override
    Result call() throws Exception {
        slowServiceClient.soooooSlow(request)
    }
}

// Created using the "slowServiceDispatcher"
class SlowServiceActor extends UntypedActor {
    @Override
    void onReceive(Object message) {
        if(message instanceof CallSlowService) {
            Request request = (message as CallSlowService).request
            Future<Result> callSlowServiceFuture = Futures.future(new CallSlowService())

            Result result = ???

            // ...now do something with result, some 15 seconds later
        }
    }
}

但正如你所看到的,我有一些问题:

  • 我认为我误解了Futures.future(...) API;我不认为这意味着构建新的Futures
  • 如何以非阻塞方式实际获取result
  • 最后:我在这里错过了什么吗?我没有利用/利用我应该采取的任何策略?

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你可以在这里有两个选择:你听一个Future正在完成,或者你对结果做了些什么:

如果你想听,你可以使用一些回调,如

final ExecutionContext ec = system.dispatcher();

future.onSuccess(new OnSuccess<String>() {
  public void onSuccess(String result) {
    if ("bar" == result) {
      //Do something if it resulted in "bar"
    } else {
      //Do something if it was some other String
    }
  }
}, ec);

另一种方式是map未来的结果。所以你有类似的东西:

callSlowServiceFuture.map(new Mapper<ReturnType1, ReturnType2>() {
  public ReturnType2 apply(ReturnType1 s) {
    // do something with 's'
  }
}, ec);

这样你就说“......当我从服务电话中得到结果的那一刻,请按照申请中的描述操纵它......”