2015-06-10 90 views
1

我正在使用Spray查詢REST端點,該端點將返回大量數據並處理幾個應該處理的項目。數據是一系列json對象。有沒有辦法將響應轉換爲這些對象的流,而不需要我將整個響應讀入內存?使用「分塊響應」噴霧

閱讀文檔時提到了"chunked responses",這似乎與我想要的一致。我如何在噴霧客戶端管道中使用它?

回答

1

由於在http://boldradius.com/blog-post/VGy_4CcAACcAxg-S/streaming-play-enumerators-through-spray-using-chunked-responses上發現了優秀的文章,我今天剛剛實現了這樣的功能。

本質上,你要做的是在你的一個Route定義中獲得RequestContext,並獲得對其「responder」Actor的引用。這是Spray將響應發回給發送原始請求的客戶端的Actor。

要發回分塊響應,必須發出響應正在啓動的信號,然後逐個發送塊,最後發出響應已完成的信號。您可以通過spray.http包中的ChunkedResponseStart,MessageChunk和ChunkedMessageEnd類來完成此操作。

本質上講我最終做的是發送像這一系列的這些類的響應:

0)一堆進口的投入與你的路由類和案例對象:

import akka.actor.{Actor, ActorRef} 
import spray.http._ 
import akka.actor.ActorRef 
import akka.util.Timeout 
import akka.pattern.ask 
import spray.http.HttpData 
import scala.concurrent.duration._ 
import scala.concurrent.{ExecutionContext, Future} 
import akka.actor.{ActorContext, ActorRefFactory, Props} 
import spray.http.{HttpData, ContentType} 
import spray.routing.RequestContext 
import scala.concurrent.ExecutionContext 
import scala.concurrent.ExecutionContext.Implicits.global 
import spray.json.RootJsonFormat 
import spray.http.MediaTypes._ 

object Messages { 
    case object Ack 
} 

1)從您的路由中得到的RequestContext的保持:

path ("asdf") { 
    get { requestContext => { 
    ... further code here for sending chunked response ... 
    } 
} 

2)啓動響應(作爲一個JSON信封將在一個JSON陣列稱爲保存響應數據「myJsonData」在這種情況下):

responder.forward(ChunkedResponseStart(HttpResponse(entity = HttpEntity(`application/json`, """{"myJsonData": ["""))).withAck(Ack)) 

3)迭代搜索結果的陣列,還送JSONified版本的響應作爲JSON數組中的元素,以逗號分隔直到最終元件被髮送 - 然後無需對於尾隨逗號:

requestContext.responder.forward(MessageChunk(HttpData(myArray.toJson).withAck(Ack)) 

if (!lastElement) { // however you work this out in your code! 
requestContext.responder.forward(MessageChunk(HttpData(",").withAck(Ack)) 
} 

4)如果有什麼可以送,收的JSON信封:

​​

和信號響應的結束:

responder.forward(ChunkedMessageEnd().withAck(Ack)) 

在我的解決方案我一直在玩Iteratees和普查員和這裏的代碼,所以我沒有將大塊大塊的工作,因爲他們都非常符合這些機制可能不適合您的需求捆綁起來。 「withAck」呼叫的要點在於,當網絡發信號表示可以接受更多數據塊時,這將導致響應者請求確認消息。理想情況下,您需要編寫代碼,以便在發送更多塊之前等待未來返回Ack消息。

我希望以上可能會給你一個起碼十個至少,正如我所說,這些概念在我鏈接到的文章中解釋得非常好!

謝謝, Duncan