我想使用akka流来收听websocket。也就是说,我希望将其视为Source
。
但是,所有official examples都将websocket连接视为Flow
。
我目前的方法是将websocketClientFlow
与Source.maybe
结合使用。当在流中没有新的TcpIdleTimeoutException
被发送时,这最终会导致上游因Message
而失败。
因此,我的问题有两个:
Source
?Flow
是唯一选项,那么如何正确处理TcpIdleTimeoutException
?通过提供流监督策略无法处理该异常。使用RestartSource
重新启动源也没有帮助,因为源不是问题。所以我尝试了两种不同的方法,为方便起见,将空闲超时设置为1秒
application.conf
akka.http.client.idle-timeout = 1s
Source.<Message>maybe()
.keepAlive(Duration.apply(1, "second"), () -> (Message) TextMessage.create("keepalive"))
.viaMat(Http.get(system).webSocketClientFlow(WebSocketRequest.create(websocketUri)), Keep.right())
{ ... }
执行此操作时,上游仍然会失败并显示TcpIdleTimeoutException
。
但是,我使用RestartFlow
final Flow<Message, Message, NotUsed> restartWebsocketFlow = RestartFlow.withBackoff(
Duration.apply(3, TimeUnit.SECONDS),
Duration.apply(30, TimeUnit.SECONDS),
0.2,
() -> createWebsocketFlow(system, websocketUri)
);
Source.<Message>maybe()
.viaMat(restartWebsocketFlow, Keep.right()) // One can treat this part of the resulting graph as a `Source<Message, NotUsed>`
{ ... }
(...)
private Flow<Message, Message, CompletionStage<WebSocketUpgradeResponse>> createWebsocketFlow(final ActorSystem system, final String websocketUri) {
return Http.get(system).webSocketClientFlow(WebSocketRequest.create(websocketUri));
}
这可以解决我可以将websocket视为Source(虽然人为地,如Stefano所解释的那样)并且每当websocketClientFlow
发生时重新启动Exception
来保持tcp连接活动。
但这并不是最佳解决方案。
答案 0 :(得分:3)
没有。 WebSocket是双向通道,因此Akka-HTTP将其建模为Flow
。如果在您的特定情况下,您只关心频道的一侧,那么您可以使用Flow
或Flow.fromSinkAndSource(Sink.ignore, mySource)
来构建一个带有“静音”一侧的Flow.fromSinkAndSource(mySink, Source.maybe)
,具体取决于您关于案件。
将根据以下内容删除非活动WebSocket连接 空闲超时设置。如果您需要保持非活动连接 活着,你可以调整你的空闲超时或注入'keep-alive' 定期发送消息。
有一个ad-hoc组合器可以注入保持活动消息,请参阅下面的示例和此Akka cookbook recipe。注意:这应该发生在客户端。
src.keepAlive(1.second, () => TextMessage.Strict("ping"))
答案 1 :(得分:0)
我希望我能正确理解你的问题。您在寻找asSourceOf
吗?
path("measurements") {
entity(asSourceOf[Measurement]) { measurements =>
// measurement has type Source[Measurement, NotUsed]
...
}
}