Source.actorRef未通过akka流流传输到websocket
我正在尝试将Source.actorRef未通过akka流流传输到websocket,akka,akka-stream,Akka,Akka Stream,我正在尝试将akka流源与websocket连接 object TestWebServer { val source1 = Source.actorRef[WsMessage](10, OverflowStrategy.dropHead) .map { case msg@WsMessage(a,b,c,d,e,f) => println("Received from stream" + msg);TextMessage(c) } import scala.concurr
akka流
源
与websocket连接
object TestWebServer {
val source1 = Source.actorRef[WsMessage](10, OverflowStrategy.dropHead)
.map { case msg@WsMessage(a,b,c,d,e,f) => println("Received from stream" + msg);TextMessage(c) }
import scala.concurrent.duration._
val source2 = Source.tick(initialDelay = 0 second, interval = 1 second, tick = TextMessage("tick"))
def main(args: Array[String]) {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val requestHandler: HttpRequest => HttpResponse = {
case req@HttpRequest(HttpMethods.GET, Uri.Path("/ws"), _, _, _) =>
req.header[UpgradeToWebSocket] match {
case Some(upgrade) => upgrade.handleMessagesWithSinkSource(Sink.ignore, source1)
case None => HttpResponse(400, entity = "Not a valid websocket request!")
}
case _: HttpRequest => HttpResponse(404, entity = "Unknown resource!")
}
val bindingFuture = Http().bindAndHandleSync(requestHandler, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
}
}
使用诸如简单Web套接字客户端(SWSC)之类的客户端,我可以看到
- 如果我将websocket连接到
source1
,
upgrade.HandleMessageWithSinkSource(Sink.ignore,source1)
我看不到SWSC的任何回复
- 如果我将websocket连接到
source2
,
upgrade.handleMessagesWithSinkSource(Sink.ignore,source2)
我可以看到SVSC控制台每隔1秒显示一条消息tick
(预期)
当我向source1
发送消息时,我可以看到从流中收到的消息。因此我相信source1
设置正确
有人知道我如何使source1
表现得像source2
?要将source1
连接到什么特殊设备
多谢各位
已更新:
- 我已经更新了代码。实际上,我在
main
之外声明了这两个源,以便我可以从另一个Actor系统使用它来发送消息。
这是共享ref以向source1
发送消息的正确方法,还是应该使用类似actorSelection
或变体的方法
- 正如弗拉基米尔·马特维耶夫(Vladimir Matveev)所提到的,我尝试过:
source1.mapMaterializedValue{ref=>ref!WsMessage(…,“x”,…);ref!WsMessage(…,“y”,…)}
但我仍然无法在SWSC中看到更新
以下是我的测试客户端的代码:
object Test {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem("my-system2")
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val source1Client = TestWebServer.source1
source1Client.mapMaterializedValue { ref => ref ! WsMessage(DateTime.now(), "x", "xx", 0, 0, 0); ref ! WsMessage(DateTime.now(), "y", "yy", 0, 0, 0) }
val source11Client = TestWebServer.source1
val actorRefClient = source11.to(Sink.ignore).run()
actorRef2 ! WsMessage(DateTime.now(), "x", "xx", 0, 0, 0)
}
}
Test
中的source1
未到达Source.actorRef
(TestWebServer中的source1
)
actorRefClient
在控制台的TestWebServer
中的source1
中从streamWsMessage(…)接收到
很抱歉,您的更新没有多大帮助。下面是一个示例程序,在我使用akka http websockets客户端和使用以下外部工具时运行良好:
我看不出这个计划和你的有什么重要区别。该程序还包括服务器和客户端,因此您可以启动服务器,然后多次启动客户端。例如,以下是两次客户端运行后的服务器输出:
Server online at http://localhost:8080/
Press RETURN to stop...
Received from stream: WsMessage(2016-06-28T08:58:21.478Z,a,x,0,0,0)
Received from stream: WsMessage(2016-06-28T08:58:21.478Z,b,y,0,0,0)
Received from stream: WsMessage(2016-06-28T08:58:29.925Z,a,x,0,0,0)
Received from stream: WsMessage(2016-06-28T08:58:29.925Z,b,y,0,0,0)
这是一个客户端输出:
TextMessage.Strict(x)
TextMessage.Strict(y)
当我运行wstaws://localhost:8080/ws
时,我看到了类似的情况
另外,无论您在哪里声明源s、接收器s或流s,它们都是不可变的蓝图,只有在run()
您的代码对我来说正确时,它们才能“行动”。您确定要将消息发送给正确的参与者吗?我在源代码上做了mapMaterializedValue{ref=>ref!WsMessage(…,“x”,…);ref!WsMessage(…,“y”,…)}
,我可以在websocket连接的输出中看到x
和y
。弗拉基米尔,请查看我的更新-谢谢!如果我使用您的代码,我现在可以看到打印出来的消息。我所看到的代码与您的代码之间的唯一区别是,您的源代码从其定义中发送消息。在我的代码中,我检索了源代码
,并向其发送了一条消息(我基本上希望外部参与者向源代码
发送一条消息)。我认为问题可能来自于在一个JVM中运行Web服务器,而我在另一个JVM(不同的程序)中启动我的测试客户机。是吗?@ccheneson,你的测试客户是什么?在我上面的示例中,有一个MainClient
对象,它是一个单独的应用程序。当然,当我与MainServer
一起测试它时,它们是在单独的JVM中启动的。@ccheneson,还有,您到底是如何“检索”源参与者的?如果没有mapMaterializedValue
并将其存储在var
或类似的东西中,我看不出有什么办法可以做到这一点,这当然不是很好。对不起,措辞不好。所谓测试客户端,我指的是我的程序,它向源代码发送WsMessage。我基本上是这样的:从外部参与者那里,我想发送一些WsMessage
消息到source
,通过WebSocketTorry糟糕的措辞将这些消息流回到客户端。所谓测试客户端,我指的是我的程序,它向源代码发送WsMessage。我基本上是这样想的:从外部参与者,我想发送一些WsMessage
消息到source
,通过WebSocket将这些消息流回到客户端(例如web浏览器),这就是为什么我将source
声明移到main
之外,以便我可以从另一个地方导入它。我觉得这也不好。如果您对如何从外部访问source
(akka remote
?)有其他想法,请告诉我-谢谢
TextMessage.Strict(x)
TextMessage.Strict(y)