簡體   English   中英

在Java中播放框架異步處理和阻止I / O.

[英]Play framework async processing and blocking I/O in Java

我的應用程序使用Play框架來處理REST請求。 我需要在http請求處理程序中執行一些可能持久的阻塞I / O操作。 與此同時,我希望有效地處理一些持久的請求。

如下所述:

http://www.playframework.com/documentation/2.2.0/JavaAsync

持久的操作可以異步運行。 另一方面,如下所述:

http://www.playframework.com/documentation/2.2.x/ThreadPools

Play框架使用相同的默認線程池,其中執行所有應用程序代碼。 至少在Java api中,不可能在不同的線程池上運行異步工作。

因此,我的問題是,是否值得以異步方式運行可能阻塞的I / O操作,考慮到這樣的操作無論如何都使用相同的線程池這一事實。 或者也許最好增加默認的線程池大小,在這種情況下不要打擾async api? (這樣至少代碼可讀性會高得多)

我建議您使用Plays F.Promise<A>設置自己的上下文並在那里運行阻塞/ cpu密集型操作。 與線程一樣,最佳解決方案取決於許多內容,例如內核數量等。

首先在applications.conf設置你的上下文:

play {
  akka {
    akka.loggers = ["akka.event.Logging$DefaultLogger", "akka.event.slf4j.Slf4jLogger"]
    loglevel = WARNING
    actor {
      default-dispatcher = {
        fork-join-executor {
          parallelism-min = 1
          parallelism-factor = 2
          parallelism-max = 6
        }
      }
      my-context {
        fork-join-executor {
          parallelism-min = 1
          parallelism-factor = 4
          parallelism-max = 16
        }
      }
    }
  }
}

然后在你的控制器中,使用Plays Promises(我正在使用Java 8)來利用你的上下文:

public static F.Promise<Result> love() {
    ExecutionContext myExecutionContext = Akka.system().dispatchers().lookup("play.akka.actor.my-context");

    F.Promise<Integer> integerPromise = F.Promise.promise(() ->
            LongRunningProcess.run(10000L)
    , myExecutionContext);

    F.Promise<Integer> integerPromise2 = F.Promise.promise(() ->
            LongRunningProcess.run(10000L)
    , myExecutionContext);

    return integerPromise.flatMap(i -> integerPromise2.map(x -> ok()));
}

這樣,您的Play應用程序仍將處理default-dispatcher程序執行上下文中的持久請求,並且阻塞/ cpu密集將在my-context運行。

我為你演示了一個非常簡短的例子,請在github上查看。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM