我试图通过Web套接字创建一个服务,该服务将接受JSON,然后在被触发时发出最后接收的值。我的示例代码是:
import akka.actor.ActorSystem
import akka.stream.scaladsl.{Broadcast, Flow, GraphDSL, ZipWith}
import akka.stream._
import play.api.libs.json._
import play.api.mvc.WebSocket
import play.core.server.{AkkaHttpServer, Server, ServerConfig}
import play.api.routing.sird._
import scala.io.StdIn
object Trigger extends App {
import GraphDSL.Implicits._
implicit val system: ActorSystem = ActorSystem("trigger")
implicit val materializer: ActorMaterializer = ActorMaterializer.create(system)
val triggerFilter = Flow[JsValue].filter(json => (json \ "trigger").isDefined)
val dataFilter = Flow[JsValue].filter(json => (json \ "trigger").isEmpty)
val triggerBatching = Flow[JsValue].conflate((acc, elem) => elem)
val dataBatching = Flow[JsValue].conflate((acc, elem) => elem)
val partial = GraphDSL.create() { implicit builder =>
val B = builder.add(Broadcast[JsValue](outputPorts = 2))
val zip = builder.add(ZipWith((msg: JsValue, trigger: JsValue) => msg))
B ~> dataFilter.async ~> dataBatching.async ~> zip.in0
B ~> triggerFilter.async ~> triggerBatching.async ~> zip.in1
FlowShape(B.in, zip.out)
}.named("partial")
val flow = Flow.fromGraph(partial)
val BufferSize: Int = 100
val Port: Int = 9001
val server: Server = AkkaHttpServer.fromRouterWithComponents(ServerConfig(
port = Some(Port),
address = "127.0.0.1"
)) { components => {
case GET(p"/ws") => WebSocket.accept[JsValue, JsValue] { request =>
flow.buffer(size = BufferSize, overflowStrategy = OverflowStrategy.backpressure)
}
}}
if (StdIn.readLine(s"${java.time.Instant.now()} - Press RETURN to stop...\n") != null) {
server.stop()
}
}
我试图实现的行为是:
但是我看到的是:
对于zip或conflate或其他阻止接收到的JSON并以最新消息响应之前合并入站JSON的事情,我有什么误解?
答案 0 :(得分:0)
conflate
适用于下游比上游慢的情况。在您的情况下,上游(即标准输入正在读取的数据)比下游要慢,因此不会发生合并。
在发送数据({"A":1}
,{"A":2}
和{"A":3}
时,最初不会收到任何内容,因为没有用于压缩数据的相应元素。在您发送触发消息之前,这些数据元素为buffered internally(默认缓冲区大小为16),它们用作下游发送的压缩对中的第二个元素。
要使用conflate
查看所需的行为,请使下游速度慢于上游速度。在您的情况下,这有点棘手,因为您是手动输入流元素。一种想法是在流中添加throttle
:
val triggerBatching =
Flow[JsValue]
.conflate((acc, elem) => elem)
.throttle(1, 10 seconds)
val dataBatching =
Flow[JsValue]
.conflate((acc, elem) => elem)
.throttle(1, 10 seconds)
然后确保您输入输入消息的速度足够快。