如何使用Akka actor处理Java期货

时间:2013-02-15 08:29:52

标签: java asynchronous akka future

我在Java Web应用程序中有一个分层架构。 UI层只是Java,服务是类型化的Akka actor,外部服务调用(WS,DB等)包含在Hystrix命令中。

UI调用服务,服务返回Akka未来。这是Akka的未来,因为我希望使用Akka期货提供的onComplete和onFailure回调来简化UI编码。然后,该服务创建执行某些映射等的未来,并将调用封装到返回Java未来的HystrixCommand。

所以在伪代码中:

UI

AkkaFuture future = service.getSomeData();

服务

public AkkaFuture getSomeData() {
    return future {
        JavaFuture future = new HystrixCommand(mapSomeData()).queue()
        //what to do here, currently just return future.get()
    }
}

问题是我想释放服务主角正在使用的线程,并且只是绑定Hystrix使用的线程。但是java的未来会阻止它,因为我必须阻止它的完成。我能想到的唯一选择(我不确定自己喜欢)是不断轮询Java未来,并在Java未来完成时完成Akka的未来。

注意:问题与Hystrix本身并没有关系,但如果有人想出一个与Hystrix特别相关的解决方案,我决定提一下。

3 个答案:

答案 0 :(得分:3)

我将@Hbf的答案标记为解决方案,因为我最终按照How do I wrap a java.util.concurrent.Future in an Akka Future?中的解释完成了Akka轮询。作为参考,我也尝试过:

  • 创建HystrixCommandExcutionHook并扩展HystrixCommand以允许回调。这不起作用,因为没有在正确的时间调用钩子。
  • 通过装饰执行者使用Guavas可听的未来在Hystrix中创建未来,然后从命令中转换未来。不起作用,因为Hystrix使用无法装饰的ThreadPoolExecutor。
编辑:我在下面添加了Akka轮询器代码,因为最初的答案是在Scala中,如果Java未来不能很好地取消,它会挂起。下面的解决方案总是在超时后离开线程。


    protected  Future wrapJavaFutureInAkkaFuture(final java.util.concurrent.Future javaFuture, final Option maybeTimeout, final ActorSystem actorSystem) {
      final Promise promise = Futures.promise();
        if (maybeTimeout.isDefined()) {
          pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option.option(maybeTimeout.get().fromNow()), actorSystem);
        } else {
          pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option. none(), actorSystem);
        }

        return promise.future();
    }

    protected  void pollJavaFutureUntilDoneOrCancelled(final java.util.concurrent.Future javaFuture, final Promise promise, final Option maybeTimeout, final ActorSystem actorSystem) {
      if (maybeTimeout.isDefined() && maybeTimeout.get().isOverdue()) {
        // on timeouts, try to cancel the Java future and simply walk away
        javaFuture.cancel(true);
        promise.failure(new ExecutionException(new TimeoutException("Future timed out after " + maybeTimeout.get())));

      } else if (javaFuture.isDone()) {
        try {
          promise.success(javaFuture.get());
        } catch (final Exception e) {
          promise.failure(e);
        }
      } else {
            actorSystem.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), new Runnable() {
          @Override
          public void run() {
            pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout, actorSystem);
          }
        }, actorSystem.dispatcher());
      }
    }

答案 1 :(得分:2)

与Scala期货相比,已知Java期货在设计方面较差。例如,查看讨论"How do I wrap a java.util.concurrent.Future in an Akka Future"

但是:也许,Hystrix提供某种onComplete回调,而不是轮询(如上面的讨论所示)?我根本不知道图书馆,但偶然发现onComplete in the Hystrix API。也许有帮助?

答案 2 :(得分:2)

从Hystrix 1.3开始,它现在也支持真正的非阻塞回调,并且更适合非阻塞和可组合的Akka / Scala Future行为:https://github.com/Netflix/Hystrix/wiki/How-To-Use#wiki-Reactive-Execution