我正在使用Akka HTTP将 Actor 与 WebSocket 客户端连接起来。该actor实现ActorPublisher[A]
并将A
的实例发布到源,该源在客户端WebSocket流中读取。
class Actor(...) extends Actor with ActorPublisher[A]
构建流程的代码如下:
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.ws._
import akka.stream.ActorMaterializer
import akka.stream.actor.ActorPublisher
import akka.stream.scaladsl._
val actor = ...
// This method gets the actor and builds its the Akka Source
// Then opens the WebSocket using that source
def connect(): Unit = {
val publisher = ActorPublisher[A](actor)
val source = Source.fromPublisher(publisher)
openWebSocket(source)
}
def openWebSocket(source: Source[A, NotUsed]): Unit = {
val flow = Http().webSocketClientFlow(WebSocketRequest(URL))
val (response, closed) = source
.map { instanceOfA =>
// Transform the instances of A to a message to send it through the websocket
TextMessage(instanceOfA.asJson)
}
.viaMat(flow)(Keep.right)
// Simple sink to print all incoming messages
.toMat(Sink.foreach {
case message: TextMessage.Strict => println(message.text)
})(Keep.both)
.run()
// Reconnect if the socket is closed
closed.foreach { _ =>
connect()
}
}
webSocketClientFlow
是使用actor源和一个简单的非相关接收器构建的。它在插座关闭之前工作得很好。此时,再次调用connect
方法。它从同一代理构建另一个源并创建一个新的WebSocket流。问题是关闭的WebSocket流仍然订阅给actor,我得到以下错误创建新的:
java.lang.IllegalStateException: ActorPublisher only supports one subscriber (which is allowed, see reactive-streams specification, rule 1.12)
at akka.stream.impl.ReactiveStreamsCompliance$.rejectAdditionalSubscriber(ReactiveStreamsCompliance.scala:59)
at akka.stream.actor.ActorPublisher.aroundReceive(ActorPublisher.scala:312)
at akka.stream.actor.ActorPublisher.aroundReceive$(ActorPublisher.scala:272)
...
如何告知代理商的取消订阅旧流程或来源?我正在停止代理并用新代理替换它,但这不是必需的。