2012-09-25 12 views
16

私は最近、Play Framework 2.0に移行しました。コントローラが実際にどのように機能しているかに関して、私に関するいくつかの質問があります。 play docsそこでPlay Framework 2.0コントローラ/ Asyncはどのように機能しますか?

が挙げられる:

道の2.0作品を再生するので、アクションコードは、可能な限り高速 (すなわち、非ブロッキング)などでなければなりません。

しかしanother part of the docsに:

  /actions { 
       router = round-robin 
       nr-of-instances = 24 
      } 

 actions-dispatcher = { 
      fork-join-executor { 
       parallelism-factor = 1.0 
       parallelism-max = 24 
      } 
     } 

コントローラの処理のために割り当てられた24人の俳優があるようです。私は、すべての要求が要求の存続期間中にそれらのアクターの1つを割り当てると思います。 そうですか?

また、parallelism-factorとは何ですか?fork-join-executorは、thread-poolとはどのように異なるのですか?

また、長い計算にはAsyncを使用する必要があります。 長い計算の対象は何ですか? 100ms? 300ms? 5秒? 10秒?私の推測は何とかなるでしょうが、それをどうやって決めるのですか?

この質問の理由は、非同期コントローラの呼び出しをテストすることは、通常の呼び出しよりも難しいことです。偽のアプリケーションを起動し、メソッドを呼び出してその戻り値をチェックするのではなく、本格的な要求を行う必要があります。

そうでない場合でも、AsyncAkka.futureのすべてをラップするのは間違いです。

私はこれを#playframework IRCチャンネルで尋ねましたが、回答はありませんでした。どのようにすればよいかわからないのは私だけではないようです。ただ、繰り返しに

  1. は、すべての要求は、アクション・プール/から1人の役者を割り当て右のこと、それか?
  2. parallelism-factorとは何ですか、なぜそれが1ですか?
  3. fork-join-executorthread-pool-executorとどのように違いますか?
  4. 計算にはどのくらいの時間がかかりますかAsync
  5. 偽のアプリケーションを起動せずに非同期コントローラメソッドをテストすることはできませんか?

ありがとうございます。

編集:IRCからいくつかのもの

IRCからいくつかのもの。

<imeredith> arturaz: i cant be boethered writing up a full reply but here are key points 
<imeredith> arturaz: i believe that some type of CPS goes on with async stuff which frees up request threads 
<arturaz> CPS? 
<imeredith> continuations 
<imeredith> when the future is finished, or timedout, it then resumes the request 
<imeredith> and returns data 
<imeredith> arturaz: as for testing, you can do .await on the future and it will block until the data is ready 
<imeredith> (i believe) 
<imeredith> arturaz: as for "long" and parallelism - the longer you hold a request thread, the more parrellism you need 
<imeredith> arturaz: ie servlets typically need a lot of threads because you have to hold the request thread open for a longer time then if you are using play async 
<imeredith> "Is it right that every request allocates one actor from /actions pool?" - yes i belive so 
<imeredith> "What does parallelism-factor mean and why is it 1?" - im guessing this is how many actors there are in the pool? 
<imeredith> or not 
<imeredith> "How does fork-join-executor differ from thread-pool-executor?" -no idea 
<imeredith> "How long should a calculation be to become wrapped in Async?" - i think that is the same as asking "how long is a piece of string" 
<imeredith> "Is is not possible to test async controller method without spinning up fake applications?" i think you should be able to get the result 
<viktorklang> imeredith: A good idea is to read the documentation: http://doc.akka.io/docs/akka/2.0.3/general/configuration.html (which says parallelism-factor is: # Parallelism (threads) ... ceil(available processors * factor)) 
<arturaz> viktorklang, don't get me wrong, but that's the problem - this is not documentation, it's a reminder to yourself. 
<arturaz> I have absolutely no idea what that should mean 
<viktorklang> arturaz: It's the number of processors available multiplied with the factor you give, and then rounded up using "ceil". I don't know how it could be more clear. 
<arturaz> viktorklang, how about: This factor is used in calculation `ceil(number of processors * factor)` which describes how big is a thread pool given for your actors. 
<viktorklang> arturaz: But that is not strictly true since the size is also guarded by your min and max values 
<arturaz> then why is it there? :) 
<viktorklang> arturaz: Parallelism (threads) ... ceil(available processors * factor) could be expanded by adding a big of conversational fluff: Parallelism (in other words: number of threads), it is calculated using the given factor as: ceil(available processors * factor) 
<viktorklang> arturaz: Because your program might not work with a parallelism less than X and you don't want to use more threads than X (i.e if you have a 48 core box and you have 4.0 as factor that'll be a crapload of threads) 
<viktorklang> arturaz: I.e. scheduling overhead gives diminishing returns, especially if ctz switching is across physical slots. 
<viktorklang> arturaz: Changing thread pool sizes will always require you to have at least basic understanding on Threads and thread scheduling 
<viktorklang> arturaz: makes sense? 
<arturaz> yes 
<arturaz> and thank you 
<arturaz> I'll add this to my question, but this kind of knowledge would be awesome docs ;) 

答えて

6
  1. メッセージは、俳優の俳優に到着すると、それは、それがそのメッセージを処理するのにかかるように、そのアクターに上保持しています。要求を同期的に処理すると(そのメッセージの処理中に応答全体を計算する)、このアクターは応答が完了するまで他の要求を処理できません。代わりに、このリクエストを受け取り次第、別のアクタに仕事を送付することができれば、リクエストを受け取ったアクタは、最初のリクエストが他のアクタによって処理されている間、次のリクエストで作業を開始できます。

  2. 俳優のために使用されるスレッドの数は「num個のCPU *並列処理ファクタ」である(あなたはしかし、最小値と最大値を指定することができます)

  3. 知らん

  4. 起こって実際の計算がある場合を除き、Iデータベース/ファイルシステムでioを実行するような、他のシステムと話しているものを非同期にする傾向があります。確かにスレッドをブロックする可能性のあるもの。しかし、メッセージを渡す際のオーバーヘッドはほとんどないので、他の俳優にすべての仕事を送っても問題はないと思います。

  5. コントローラのテスト方法については、Play Documentation on functional testsを参照してください。

+0

ポイントについて1.他のアクターにタスクをオフに送信するだけではなくのために/ 150を好きに行動スレッドの数を増やすことの利点は何(150の同時アクションの場合)? – arturaz

+0

このように考える。あなたはあなたの机の上で何百ものものを積んでいます。どちらがより効率的でしょうか?パイルを外して、それが終わるまで作業し、次の作業をしてください。または、最初の150人を取って、150人の異なるものの間であなたの時間を分割するそれぞれの小さな作品を作ってください。最初の方が効率的です。コンテキストスイッチで時間を無駄にしないからです。ここでも同じです。 – stew

+0

しかし、タスクを別のアクタに送信すると、コンテキスト切り替えにもつながります。そのメリットは何ですか? –

1

あなたがテストのためにこれを行うことができますようだ:

object ControllerHelpers { 
    class ResultExtensions(result: Result) { 
    /** 
    * Retrieve Promise[Result] from AsyncResult 
    * @return 
    */ 
    def asyncResult = result match { 
     case async: AsyncResult => async.result 
     case _ => throw new IllegalArgumentException(
     "%s of type %s is not AsyncResult!".format(result, result.getClass) 
    ) 
    } 

    /** 
    * Block until result is available. 
    * 
    * @return 
    */ 
    def await = asyncResult.await 

    /** 
    * Block until result is available. 
    * 
    * @param timeout 
    * @return 
    */ 
    def await(timeout: Long) = asyncResult.await(timeout) 

    /** 
    * Block for max 5 seconds to retrieve result. 
    * @return 
    */ 
    def get = await.get 
    } 
} 

    implicit def extendResult(result: Result) = 
    new ControllerHelpers.ResultExtensions(result) 


    val result = c.postcodeTimesCsv()(request(params)).get 
    status(result) should be === OK 
関連する問題