我正在使用Spray查詢REST端點,該端點將返回大量數據並處理幾個應該處理的項目。數據是一系列json對象。有沒有辦法將響應轉換爲這些對象的流,而不需要我將整個響應讀入內存?使用「分塊響應」噴霧
閱讀文檔時提到了"chunked responses",這似乎與我想要的一致。我如何在噴霧客戶端管道中使用它?
我正在使用Spray查詢REST端點,該端點將返回大量數據並處理幾個應該處理的項目。數據是一系列json對象。有沒有辦法將響應轉換爲這些對象的流,而不需要我將整個響應讀入內存?使用「分塊響應」噴霧
閱讀文檔時提到了"chunked responses",這似乎與我想要的一致。我如何在噴霧客戶端管道中使用它?
由於在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