假设我有一个演员UserActor
知道如何处理传入的消息以及如何发送新消息,我想处理Akka-Http中的Web套接字,所以我创建了Flow[Message, Message, NotUsed]
。
在这里,我们将新邮件作为JSON获取并将其发送到UserActor
。完成源后,我收到SourceDied
消息:
val incomingMessages: Sink[Message, NotUsed] =
Flow[Message]
.mapAsync(1) {
case TextMessage.Strict(text) => Future.successful(text)
case TextMessage.Streamed(msg) => msg.runFold("")(_ + _)
}
.map(decode[IncomingMessage])
.collect { case Right(msg) => msg }
.map(_.toMessage)
.to(Sink.actorRef[ChatMessage](userActor, SourceDied))
我在out
注册了UserActor
,我们会发送消息:
val outgoingMessages: Source[Message, NotUsed] =
Source
.actorRef[ChatMessage](20, OverflowStrategy.fail)
.mapMaterializedValue { outActor =>
userActor ! Connect(outActor)
NotUsed
}
.map((x: ChatMessage) => OutgoingMessage.fromMessage(x))
.map((outMsg: OutgoingMessage) => TextMessage(outMsg.asJson.toString))
Flow.fromSinkAndSource(incomingMessages, outgoingMessages)
但是,UserActor是每个用户一个,每个用户可以同时打开多个套接字。所以我只是收集outs
来设置UserActor
内部并向每个人发送信息。它很好用。
但是,当来源向我发送终止消息时(SourceDied
在我的情况下),我不知道out
这个source
被分配到哪个 - 我无法确定哪个out
我应该告知完成情况,然后从我的outs
集中删除。
答案 0 :(得分:1)
一个想法是更改Flow
以为每个连接获取唯一标识符:
def websocketFlow(connectionId: String): Flow[Message, Message, NotUsed] = {
val incomingMessages: Sink[Message, NotUsed] =
...
.to(Sink.actorRef[ChatMessage](userActor, SourceDied(connectionId)))
val outgoingMessages: Source[Message, NotUsed] =
Source
.actorRef[ChatMessage](20, OverflowStrategy.fail)
.mapMaterializedValue { outActor =>
userActor ! Connect(connectionId, outActor)
NotUsed
}
...
Flow.fromSinkAndSource(incomingMessages, outgoingMessages)
}
显然,您需要调整SourceDied
和Connect
消息以包含连接ID(例如,在这种情况下,可以使用类似java.util.UUID.randomUUID.toString
的内容生成)。然后在UserActor
中,将Set
替换为Map
,其中的键是连接ID。使用Map
可以查找连接actor并根据需要将其删除。
答案 1 :(得分:0)
因此,正如我从@chunjef的回答中所理解的那样,没有直接的方法可以做到这一点。我个人决定不使用随机ID生成,而是在套接字和UserActor
之间再使用一个Actor。
基本上,现在我有SocketHandlerActor(userActor: ActorRef)
替换套接字创建部分中的UserActor
。它只是连接到UserActor
并在套接字和UserActor
之间发送所有消息。
但是,当SocketHandlerActor
收到SourceDied
条信息时,它只会执行操作,然后使用out
杀死PoisionPill
和自我。收到UserActor
消息后,outs
会将其从自己的Termination
列表中删除。