简体   繁体   English

如何使用Akka actor处理Java期货

[英]How to handle Java futures with Akka actors

I have a layered architecture in a Java web application. 我在Java Web应用程序中有一个分层架构。 The UI layer is just Java, services are typed Akka actors and external service calls (WS, DB etc.) are wrapped in Hystrix commands. UI层只是Java,服务是类型化的Akka actor,外部服务调用(WS,DB等)包含在Hystrix命令中。

THe UI calls the service and the service returns an Akka future. UI调用服务,服务返回Akka未来。 It's an Akka future because I want to make UI coding simpler with the onComplete and onFailure callbacks that Akka futures provide. 这是Akka的未来,因为我希望使用Akka期货提供的onComplete和onFailure回调来简化UI编码。 The service then creates the future that does some mapping etc. and wraps a call to a HystrixCommand that returns a Java future. 然后,该服务创建执行某些映射等的未来,并将调用包装回返回Java未来的HystrixCommand。

So in pseudocode: 所以在伪代码中:

UI UI

AkkaFuture future = service.getSomeData();

Service 服务

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

The problem is that I would like to free up the thread the service actor is using and just tie up the threads that Hystrix uses. 问题是我想释放服务主角正在使用的线程,并且只是绑定Hystrix使用的线程。 But the java future prevents that because I have to block on it's completion. 但是java的未来会阻止它,因为我必须阻止它的完成。 The only option I can think of (which I'm not sure I like) is to poll the Java future(s) constantly and complete the Akka future when the Java future finishes. 我能想到的唯一选择(我不确定自己喜欢)是不断轮询Java未来,并在Java未来完成时完成Akka的未来。

Note: the question isn't really related to Hystrix per se, but I decided to mention it if somebody comes up with a solution specifically related to Hystrix. 注意:问题与Hystrix本身并没有真正的关系,但如果有人想出一个与Hystrix特别相关的解决方案,我决定提一下。

I'm marking the answer by @Hbf as a solution, since I ended up doing an Akka poller as explained in How do I wrap a java.util.concurrent.Future in an Akka Future? 我正在用@Hbf作为解决方案来标记答案,因为我最终做了一个Akka poller,如在Akka Future如何包装java.util.concurrent.Future中所述? . For reference I also tried: 作为参考,我也尝试过:

  • Creating a HystrixCommandExcutionHook and extending HystrixCommand to allow callbacks. 创建HystrixCommandExcutionHook并扩展HystrixCommand以允许回调。 That didn't work because the hook wasn't called at the right time. 这没有用,因为没有在正确的时间调用钩子。
  • Using Guavas listenable future by having a decorated executor create the futures inside Hystrix and then casting the futures from the commands. 通过装饰执行器使用Guavas可听的未来在Hystrix内创建未来,然后从命令中转换期货。 Doesn't work because Hystrix uses a ThreadPoolExecutor which can't be decorated. 不起作用,因为Hystrix使用无法装饰的ThreadPoolExecutor。

EDIT: I'm adding the Akka poller code below, since the original answer was in Scala and it hangs if the Java future doesn't cancel nicely. 编辑:我在下面添加了Akka轮询代码,因为最初的答案是在Scala中,如果Java未来不能很好地取消它会挂起。 The solution below always walks away from threads after a timeout. 下面的解决方案总是在超时后离开线程。


    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());
      }
    }

Java futures are known to be inferior in design compared to something like Scala futures. 与Scala期货相比,已知Java期货在设计上较差。 Take a look at the discussion "How do I wrap a java.util.concurrent.Future in an Akka Future" , for example. 例如,看看讨论“如何在Akka Future中包装java.util.concurrent.Future”

But: Maybe, instead of polling (as suggested in the above discussion), Hystrix offers some kind of onComplete callback? 但是:也许,而不是轮询(如上面的讨论所示),Hystrix提供某种onComplete回调? I do not know the library at all but stumbled upon an onComplete in the Hystrix API . 我根本不知道这个库,但偶然发现了Hystrix API中onComplete Maybe it helps? 也许有帮助吗?

从Hystrix 1.3开始,它现在也支持真正的非阻塞回调,并且非常适合非阻塞和可组合的Akka / Scala Future行为: https//github.com/Netflix/Hystrix/wiki/How-To -使用#维基无功执行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM