Akka MergeHub和BroadcastHub通过Actor通过websockets支持多个客户端

时间:2017-08-20 22:12:20

标签: scala playframework websocket akka akka-stream

目前我使用带有

的websocket
  • 1个客户
  • 服务器端的2个来源

服务器推送keepAlive消息并回复客户端的请求。

现在我想稍微调整一下,增加处理 n 客户的可能性。

所以我看了一下:

https://github.com/playframework/play-scala-chatroom-example

这基本上是n-Inlet ~> n-Outlet所以如果n个客户端中的任何一个通过各自的websocket写入内容,所有这些客户端都会收到通知(包括其自身)。

我需要的是更复杂的,因为服务器应该

  1. 仍然会向所有已连接的客户端所有发送keepAlive消息
  2. 如果其中一个客户要求/触发服务器端“事件”,则再次全部应通知客户端。
  3. 所以它基本上只是我抽象思维方式中的一步。

    天真,因为我认为它可以通过以下方式完成:

    type AllowedWSMessage = String
    
    val myActor = system.actorOf(Props{new myActor}, "myActor")
    val myActorSink = Sink.actorRefWithAck(myActor, "init", "acknowledged", "completed")
    import scala.concurrent.duration._
    
    val tickingSource: Source[AllowedWSMessage, Cancellable] =
    Source.tick(initialDelay = 1 second, interval = 10 seconds, tick = NotUsed)
      .map(_ => "Staying Alive")
    
    val serverMessageSource = Source
    .queue[AllowedWSMessage](10, OverflowStrategy.backpressure)
    .mapMaterializedValue { queue => myActor ! InitTunnel(queue)}
    
    val serverSource: Source[AllowedWSMessage, Cancellable] = tickingSource.merge(serverMessageSource)
    
    private val (clientSink, clientSource) =
    {
        // Don't log MergeHub$ProducerFailed as error if the client disconnects.
        // recoverWithRetries -1 is essentially "recoverWith"
        val source = MergeHub.source[AllowedWSMessage]
          .log("source")
          .recoverWithRetries(-1, { case _: Exception ⇒ Source.empty})
    
        val sink: Sink[AllowedWSMessage, Source[AllowedWSMessage, NotUsed]] = BroadcastHub.sink[AllowedWSMessage]
        source.via(serverSource).toMat(sink)(Keep.both).run()
      }
    

    (注意source.via(serverSource)...

    但当然不是那么容易。

    最终我想要的基本上是:

    (Client -> WebSocket ->) MergeHub ~> myActor ~> BroadcastHub (-> WebSocket -> Client)
    

    现在我想知道,这样做的优雅方式是什么? 或者MergeHub和BroadcastHub是否适合应对这一挑战?

1 个答案:

答案 0 :(得分:1)

You have your server source and sink, you said they already work, so I'm not digging into them.

returning

Easy as that, hope the knot in your head unravels now :)