在Akka中使用严格的WebSocket消息和流式WebSocket消息

在Akka中使用严格的WebSocket消息和流式WebSocket消息,websocket,akka,akka-stream,akka-http,Websocket,Akka,Akka Stream,Akka Http,我正在尝试使用Akka HTTP构建web套接字服务。我需要处理全部到达的严格消息,以及处理以m个多帧到达的流式消息。我使用带有handleWebSocketMessages()的路由将web套接字的处理传递给流。我的代码如下所示: val route: Route = get { handleWebSocketMessages(createFlow()) } def createFlow(): Flow[Message, Message, Any] = Flow[Messag

我正在尝试使用Akka HTTP构建web套接字服务。我需要处理全部到达的严格消息,以及处理以m个多帧到达的流式消息。我使用带有handleWebSocketMessages()的路由将web套接字的处理传递给流。我的代码如下所示:

val route: Route =
  get {
    handleWebSocketMessages(createFlow())
  }

def createFlow(): Flow[Message, Message, Any] = Flow[Message]
  .collect {
    case TextMessage.Strict(msg) ⇒ msg
    case TextMessage.Streamed(stream) => ??? // <= What to do here??
  }
  .via(createActorFlow())
  .map {
    case msg: String ⇒ TextMessage.Strict(msg)
  }

def createActorFlow(): Flow[String, String, Any] = {
  // Set Up Actors
  // ... (this is working)
  Flow.fromSinkAndSource(in, out)
}
val route: Route =
  get {
    handleWebSocketMessages(createFlow())
  }

def createFlow(): Flow[Message, Message, Any] = Flow[Message]
  .collect {
    case TextMessage.Strict(msg) ⇒ 
      Future.successful(MyCaseClass(msg))
    case TextMessage.Streamed(stream) => stream
      .limit(100)                   // Max frames we are willing to wait for
      .completionTimeout(5 seconds) // Max time until last frame
      .runFold("")(_ + _)           // Merges the frames
      .flatMap(msg => Future.successful(MyCaseClass(msg)))
  }
  .mapAsync(parallelism = 3)(identity)
  .via(createActorFlow())
  .map {
    case msg: String ⇒ TextMessage.Strict(msg)
  }

def createActorFlow(): Flow[MyCaseClass, String, Any] = {
  // Set Up Actors as source and sink (not shown)
  Flow.fromSinkAndSource(in, out)
}
但现在我的流必须处理未来的[String],而不仅仅是字符串,我不知道如何处理这些字符串,特别是因为显然我需要按顺序处理消息

我确实看到了这个akka问题,这似乎有点相关,但不完全是我需要的(我不这么认为?)


任何帮助都会被感激的

折叠听起来是个明智的选择。处理流中的未来数据可以使用(例如)

请注意,mapAsync确实保留了传入消息的顺序,如所示

另一方面,处理流式WS-messages的其他合理预防措施可能是使用completionTimeout并限制要折叠的消息的绑定时间和空间(例如)


基于以下(感谢svezfaz)答案的最终答案是这样的:

val route: Route =
  get {
    handleWebSocketMessages(createFlow())
  }

def createFlow(): Flow[Message, Message, Any] = Flow[Message]
  .collect {
    case TextMessage.Strict(msg) ⇒ msg
    case TextMessage.Streamed(stream) => ??? // <= What to do here??
  }
  .via(createActorFlow())
  .map {
    case msg: String ⇒ TextMessage.Strict(msg)
  }

def createActorFlow(): Flow[String, String, Any] = {
  // Set Up Actors
  // ... (this is working)
  Flow.fromSinkAndSource(in, out)
}
val route: Route =
  get {
    handleWebSocketMessages(createFlow())
  }

def createFlow(): Flow[Message, Message, Any] = Flow[Message]
  .collect {
    case TextMessage.Strict(msg) ⇒ 
      Future.successful(MyCaseClass(msg))
    case TextMessage.Streamed(stream) => stream
      .limit(100)                   // Max frames we are willing to wait for
      .completionTimeout(5 seconds) // Max time until last frame
      .runFold("")(_ + _)           // Merges the frames
      .flatMap(msg => Future.successful(MyCaseClass(msg)))
  }
  .mapAsync(parallelism = 3)(identity)
  .via(createActorFlow())
  .map {
    case msg: String ⇒ TextMessage.Strict(msg)
  }

def createActorFlow(): Flow[MyCaseClass, String, Any] = {
  // Set Up Actors as source and sink (not shown)
  Flow.fromSinkAndSource(in, out)
}

谢谢svezfaz。你的提示帮助我解决了这个问题。我现在已经开始工作了。为这个案子增加更多的方便方法已经在我们的雷达上了。顺便说一句,请注意:谢谢。我同意这一问题。我希望这个问题/答案能同时帮助人们解决问题。关于这个:case msg@TextMessage.Streamed(t)=>msg.toStrict(5秒)。flatMap(…)?
val route: Route =
  get {
    handleWebSocketMessages(createFlow())
  }

def createFlow(): Flow[Message, Message, Any] = Flow[Message]
  .collect {
    case TextMessage.Strict(msg) ⇒ 
      Future.successful(MyCaseClass(msg))
    case TextMessage.Streamed(stream) => stream
      .limit(100)                   // Max frames we are willing to wait for
      .completionTimeout(5 seconds) // Max time until last frame
      .runFold("")(_ + _)           // Merges the frames
      .flatMap(msg => Future.successful(MyCaseClass(msg)))
  }
  .mapAsync(parallelism = 3)(identity)
  .via(createActorFlow())
  .map {
    case msg: String ⇒ TextMessage.Strict(msg)
  }

def createActorFlow(): Flow[MyCaseClass, String, Any] = {
  // Set Up Actors as source and sink (not shown)
  Flow.fromSinkAndSource(in, out)
}