Playframework 使用分块传输编码从scala Play服务器流式传输案例类对象

Playframework 使用分块传输编码从scala Play服务器流式传输案例类对象,playframework,akka,akka-stream,akka-http,Playframework,Akka,Akka Stream,Akka Http,因此,我使用Play framework 2.7来设置流媒体服务器。我试图做的是流式处理大约500个大小相似的定制案例类对象 这是生成流的控制器的一部分- def generate: Action[AnyContent] = Action { val products = (1 to 500).map(Product(_, "some random string")).toList Ok.chunked[Product](Source(products))

因此,我使用Play framework 2.7来设置流媒体服务器。我试图做的是流式处理大约500个大小相似的定制案例类对象

这是生成流的控制器的一部分-

def generate: Action[AnyContent] = Action {
    val products = (1 to 500).map(Product(_, "some random string")).toList
    Ok.chunked[Product](Source(products))
  }
其中,
Product
是我正在使用的自定义案例类。隐式
可写
将此对象反序列化为json

这是处理这个流的控制器的一部分-

def process(): Action[AnyContent] = Action.async {
    val request = ws.url(STREAMING_URL).withRequestTimeout(Duration.Inf).withMethod("GET")
    request.stream().flatMap {
      _.bodyAsSource
        .map(_.utf8String)
        .map { x => println(x); x }
        .fold(0) { (acc, _) => acc + 1 }
        .runWith(Sink.last)
        .andThen {
          case Success(v) => println(s"Total count - $v")
          case Failure(_) => println("Error encountered")
        }
    }.map(_ => Ok)
  }
我所期望的是,我的case类的每个对象都作为单个块进行传输,并以同样的方式进行接收,以便它们可以单独序列化并由接收方使用。这意味着,使用上面的代码,我的期望是我应该收到正好500个块,但是这个值总是大于这个值

我能看到的是,在这500个对象中,正好有一个对象以分割方式传输,并以2个块而不是1个块传输

这是一个正常的对象,如接收端所示-

{
  "id" : 494,
  "name" : "some random string"
}
这是一个一分为二的物体-

{
  "id" : 463,
  "name" : "some random strin
g"
}
因此,不能将其序列化回my
Product
case类的实例中

但是,如果我在发送方控制器中对源代码进行了某种限制,我会像预期的那样接收块

例如,当我每秒只传输5个元素时,这就可以完全正常工作-

def generate: Action[AnyContent] = Action {
    val products = (1 to 500).map(Product(_, "some random string")).toList
    Ok.chunked[Product](Source(products).throttle(5, 1.second))
  }
有人能帮我理解为什么会发生这种情况吗?

如前所述,有一个
JsonFraming
将有效的JSON对象从传入的
ByteString
流中分离出来

在你的情况下,你可以这样尝试

  _.bodyAsSource.via(JsonFraming.objectScanner(Int.MaxValue)).map(_.utf8String)

只是猜测一下,但可能在不限制发送程序的情况下,发送程序生成元素的速度比发送它们的速度要快,因此它会将块打包到极限,并分割一些字符串。通过节流,可能有足够的时间在每个块中放置一个元素。此信息可能会解释:
另一个陷阱是参与者消息可能会丢失,在这种情况下必须重新传输。否则将导致接收侧出现孔。
from。我想您将不得不处理背压。@Felipe我认为这不是流的问题-这是演员的情况,流是在演员之上构建的,以避免这些陷阱。您确定这不仅仅是
println
的并发性问题吗?你能试着用日志记录来代替它,看看它是否还能复制吗?不是,因为我也在计算接收端的块数。他们比预期的要多。