我正在使用Akka WebSockets进行客户端-服务器通信。
source
.viaMat(Http().webSocketClientFlow(httpReq, settings))(Keep.both)
.toMat(sink)(Keep.both)
.run()
来源所在的位置
val source = Source.actorRef[Object](Int.MaxValue,OverflowStrategy.fail)
接收器将所有消息转发到ClientActor
。
val requestHandler: HttpRequest => HttpResponse = {
case req @ HttpRequest(GET, Uri.Path("/"), _, _, _) =>
req.header[UpgradeToWebSocket] match {
case Some(upgrade: UpgradeToWebSocket) =>
/**
* Create an ActorRef for the client. Sending messages to this actor replies to the client.
* fanout = false, because there is only one output (no broadcasting).
*/
val source: Source[Object, ActorRef] = Source.actorRef[Object](Int.MaxValue, OverflowStrategy.fail)
val (clientActor: ActorRef, publisher) = source
.via(flow)
.toMat(Sink.asPublisher(fanout = false))(Keep.both).run()
// receives messages from the client
val sink: Sink[Message, NotUsed] = Common.getSink(messageHandler, clientActor)
upgrade.handleMessagesWithSinkSource(sink, Source.fromPublisher(publisher))
case None =>
HttpResponse(400, entity = "Not a valid websocket request!")
}
case r: HttpRequest =>
r.discardEntityBytes() // important to drain incoming HTTP Entity stream
HttpResponse(404, entity = "Unknown resource!")
}
然后sink
将所有消息转发到ServerActor
。
def receive: PartialFunction[Any, Unit] = {
case Terminated(sender) =>
logger.info(s"Detected that client disconnected: $sender")
但是,当我使用clientActor ! PoisonPill
停止clientActor时,服务器将花费几分钟的时间来检测到clientActor已断开连接。我需要在clientActor或serverActor中进行哪些更改才能立即检测到断开连接?任何指针都会被应用。
我尝试使用system.context.terminate()
,并且ServerActor会立即检测到断开连接,但随后不允许我创建新的ClientActor。我遇到“ Why does Akka fail with "IllegalStateException: cannot create children while terminating or terminated" when testing with ScalaTest?”错误。
我进行了一些挖掘,发现Akka WebSocket使用streamSupervisor
演员进行通信,并且clientActor
和serverActor
都在监视这些streamSupervisor
演员。
这里的期望是要立即检测到serverActor
actor上的客户端断开连接。
答案 0 :(得分:0)
您可以将Sink.actorRef
用于流的接收器。客户端终止连接后,actor将收到此消息,您可以毒害与WebSocket对应的子actor。