使用play框架和akka重定向websocket连接

时间:2017-05-10 18:27:57

标签: playframework websocket akka

我想将一个websocket连接重定向到另一个播放实例,但还没有想出如何做到这一点。

基本上我有一个akka集群,节点和演员之间的负载平衡(使用akka路由器),到目前为止一直很好,它正在工作。

因此我需要在一个播放实例中接收websocket连接,但我想使用路由器(akka actor)将其转发到另一个播放实例。这很重要,因为我实现了我的负载平衡要求。

接受websocket连接的典型路由如下所示:

def socket = WebSocket.accept[JsValue, JsValue] { request =>
    ActorFlow.actorRef(out => MyWebSocketActor.props(out))
}

问题是这会立即返回一个Flow(akka流)并建立websocket连接,我需要转发请求并在另一个Play实例中建立连接。此转发必须通过actor才能维持负载平衡。我可以很好地转发消息,但我需要转发初始连接。

感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:1)

在这篇文章中找到了botkop的解决方案。根据akka http文档似乎是正确的(有其他方法,但要么更复杂或被弃用)

Websocket Proxy using Play 2.6 and akka streams

def websocketFlow: Flow[Message, Message, Future[WebSocketUpgradeResponse]] =
   Http().webSocketClientFlow(WebSocketRequest("ws://localhost:9000/upper-socket"))

def proxySocket: WebSocket = WebSocket.accept[String, String] { _ =>
   Flow[String].map(s => TextMessage(s))
     .via(websocketFlow)
     .map(_.asTextMessage.getStrictText)
}

以上方法可以重定向到静态URL,也可以是其他播放实例。这个其他实例可以实现websockets,就好像它是一个独立的解决方案。

在我的情况下,我需要负载平衡,所以,添加到上面,方法" websocketFlow"我首先需要使用一个akka actor,它是一个集群中的路由器,并要求它提供一个目的地,这取代了" localhost:9000"。这并不完美,因为我需要向一个演员发送一条消息,以便找出我要代理websocket的实例,并且只有在我可以代理请求之后。一个更好的解决方案是路由器角色可以完成" websocketFlow"的工作。

完整的解决方案是大到此处发布,但akka群集和路由在其文档中得到了很好的解释http://doc.akka.io/docs/akka/current/java/cluster-usage.html