2012-09-25 23 views
16

Gần đây tôi đã chuyển sang Play framework 2.0 và có một số câu hỏi liên quan đến việc bộ điều khiển thực sự hoạt động như thế nào trong khi chơi.Làm thế nào chính xác Play bộ điều khiển khung 2.0/Async làm việc?

Trong play docs có được nhắc đến:

Do cách chơi công trình 2.0, mã hành động phải được nhanh như có thể (tức là không chặn.).

Tuy nhiên trong 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 
      } 
     } 

Có vẻ như rằng có 24 diễn viên được phân bổ cho các bộ điều khiển xử lý. Tôi đoán mọi yêu cầu phân bổ một trong những yêu cầu đó trong suốt thời gian yêu cầu. Đúng không?

Ngoài ra, nghĩa là gì parallelism-factor có nghĩa là gì và cách nào fork-join-executor khác với thread-pool?

Ngoài ra - tài liệu nên nói rằng Async nên được sử dụng để tính toán dài. Điều gì đủ điều kiện để tính toán dài? 100ms? 300ms? 5 giây? 10 giây? Đoán của tôi sẽ là bất cứ điều gì trong một giây, nhưng làm thế nào để xác định điều đó?

Lý do của câu hỏi này là việc kiểm tra cuộc gọi điều khiển không đồng bộ là khó hơn các cuộc gọi thông thường. Bạn phải quay lên một ứng dụng giả mạo và thực hiện một yêu cầu chính thức thay vì chỉ gọi một phương thức và kiểm tra giá trị trả về của nó.

Ngay cả khi đó không phải là trường hợp, tôi nghi ngờ rằng gói tất cả mọi thứ trong AsyncAkka.future là cách.

Tôi đã yêu cầu điều này trong #playframework kênh IRC nhưng không có câu trả lời và có vẻ như tôi không phải là người duy nhất không chắc chắn mọi thứ nên được thực hiện như thế nào.

Chỉ cần nhắc lại:

  1. Có đúng rằng mọi yêu cầu phân bổ một diễn viên từ/hồ bơi hành động?
  2. parallelism-factor có nghĩa là gì và tại sao lại là 1?
  3. Làm thế nào để fork-join-executor khác với thread-pool-executor?
  4. Cần tính bao lâu để được bao bọc trong Async?
  5. Không thể kiểm tra phương pháp điều khiển không đồng bộ mà không cần quay lên các ứng dụng giả mạo?

Cảm ơn trước.

Chỉnh sửa: một số nội dung từ IRC

Một số công cụ từ 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 ;) 

Trả lời

6
  1. Khi một thư đến trên một diễn viên một diễn viên, nó giữ vào diễn viên rằng miễn là nó cần để xử lý thông điệp đó. Nếu bạn xử lý yêu cầu một cách đồng bộ (tính toán toàn bộ phản hồi trong quá trình xử lý thông báo đó), thì Tác nhân này không thể phục vụ các yêu cầu khác cho đến khi đáp ứng được thực hiện. Nếu bạn có thể, khi nhận được yêu cầu này, gửi tác phẩm đến một diễn viên khác, diễn viên nhận được yêu cầu có thể bắt đầu làm việc với yêu cầu tiếp theo trong khi yêu cầu đầu tiên đang được các diễn viên khác làm việc.

  2. Số lượng đề sử dụng cho các diễn viên là "num cpu * song song yếu tố" (bạn tuy nhiên có thể xác định min và max)

  3. Dunno

  4. Trừ khi có những tính toán thực xảy ra, tôi d có xu hướng làm cho bất cứ điều gì async đó là nói chuyện với một số hệ thống khác, như làm io với một cơ sở dữ liệu/hệ thống tập tin. Chắc chắn mọi thứ có thể chặn luồng. Tuy nhiên, vì có quá ít chi phí trong việc truyền tải thông điệp, tôi không nghĩ sẽ có vấn đề với việc chỉ gửi tất cả tác phẩm đến các diễn viên khác.

  5. Xem Play Documentation on functional tests về cách kiểm tra bộ điều khiển của bạn.

+0

Về điểm 1. lợi ích của việc gửi công việc ra thành diễn viên khác thay vì chỉ tăng số lượng đề cho là gì/hành động để thích 150 (cho 150 hành động đồng thời)? – arturaz

+0

Hãy suy nghĩ về nó theo cách này. Bạn có hàng trăm thứ để làm trên bàn làm việc của bạn. Mà sẽ hiệu quả hơn? kéo một cọc ra, làm việc trên nó cho đến khi nó được thực hiện, sau đó làm việc trên kế tiếp. Hoặc lấy 150 người đầu tiên trong số họ và làm việc một chút trên mỗi người chia thời gian của bạn giữa 150 thứ khác nhau. Việc đầu tiên là hiệu quả hơn bởi vì bạn không lãng phí thời gian vào "chuyển mạch bối cảnh". Điều tương tự cũng đúng ở đây. – stew

+0

Nhưng việc gửi tác vụ đến một diễn viên khác cũng dẫn đến chuyển đổi ngữ cảnh. Lợi ích là gì? –

1

Dường như bạn có thể làm điều này để thử nghiệm:

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