4

JavaWebアプリケーションに階層化アーキテクチャがあります。UIレイヤーは単なるJavaであり、サービスはAkkaアクターと入力され、外部サービス呼び出し(WS、DBなど)はHystrixコマンドでラップされます。

UIがサービスを呼び出し、サービスがAkkaの未来を返します。Akka先物が提供するonCompleteおよびonFailureコールバックを使用して、UIコーディングを簡単にしたいので、これはAkka先物です。次に、サービスは、マッピングなどを行うfutureを作成し、Javafutureを返す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 Futureは、その完了をブロックする必要があるため、それを防ぎます。私が考えることができる唯一のオプション(私が好きかどうかはわかりませんが)は、Java Futureを常にポーリングし、JavaFutureが終了したときにAkkaFutureを完了することです。

注:質問は実際にはHystrix自体に関連しているわけではありませんが、誰かがHystrixに特に関連する解決策を思いついた場合は、それについて言及することにしました。

4

3 に答える 3

3

「AkkaFutureでjava.util.concurrent.Futureをラップするにはどうすればよいですか?」で説明されているように、Akkaポーラーを実行することになったので、@Hbfによる回答を解決策としてマークしています。。参考までに、私も試しました:

  • HystrixCommandExcutionHookを作成し、HystrixCommandを拡張してコールバックを許可します。フックが適切なタイミングで呼び出されなかったため、これは機能しませんでした。
  • 装飾されたエグゼキュータにHystrix内に先物を作成させ、コマンドから先物をキャストすることにより、Guavasのリッスン可能な先物を使用します。Hystrixは装飾できないThreadPoolExecutorを使用しているため、機能しません。

編集:元の答えはScalaにあり、Javaの将来がうまくキャンセルされない場合はハングするため、以下にAkkaポーラーコードを追加しています。以下の解決策は、タイムアウト後に常にスレッドから離れます。


    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());
      }
    }
于 2013-03-13T18:57:44.680 に答える
2

Java先物は、Scala先物のようなものと比較して設計が劣っていることで知られています。たとえば、「java.util.concurrent.FutureをAkkaFutureでラップするにはどうすればよいですか」というディスカッションをご覧ください。

しかし:たぶん、(上記の議論で示唆されているように)ポーリングの代わりに、Hystrixはある種のonCompleteコールバックを提供しますか?私はライブラリをまったく知りませんがonComplete、HystrixAPIでに遭遇しました。多分それは役立ちますか?

于 2013-02-27T23:29:59.987 に答える
2

Hystrix 1.3以降、真の非ブロッキングコールバックもサポートするようになりました。これは、非ブロッキングで構成可能なAkka / Scala Futureの動作にはるかによく適合します:https ://github.com/Netflix/Hystrix/wiki/How-To -Use#wiki-Reactive-Execution

于 2013-10-01T21:36:57.480 に答える