![](/img/trans.png)
[英]Akka-Http WebSocket: Akka stream use WebSocket as a sink
[英]Akka HTTP WebSocket Server How to declare Source based on Sink content when building Flow for message handlement?
我正在玩 Akka Stream/Http 并试图弄清楚如何在 websocket 服务器中执行以下操作(希望不使用 Actor 模式):
1.客户端初始连接请求,握手后,服务器会监听客户端的初始Message
,格式为json
。
2. 服务器收到TextMessage.Strict
后,如果有效,它将丰富Message
以构建“谓词”(例如过滤器映射),然后服务器将使用该“谓词”构建Source[Message, _]
。
我尝试使用handleMessagesWithSinkSource
但在我看来这个 API 的意图是独立生成Sink
和Source
(请参阅路由/ws
)。 我也尝试使用handleWebSocketMessages
(请参阅路由ws/filter
),但对我来说,Flow 中的 Sink(inlet) 和 Source(outlet) 之间没有连接。 我理解Sink
在这里应该如何工作一定是错误的:
我的路线:
(path("ws") & get & pathEndOrSingleSlash) {
extractUpgradeToWebSocket { upgrade =>
complete(upgrade.handleMessagesWithSinkSource(Sink.ignore,
getSourceAll)
} // this route is working fine, pushing all event Messages to client once connected
} ~
(path("ws" / "filter") & get & pathEndOrSingleSlash) {
handleWebSocketMessages(getSourceFiltered)
} // this route I cannot figure out a way to build `Flow` dynamically based on `Sink`...
getSourceAll
和getSourceFiltered
的想法
val getSourceAll: Source[Message, NotUsed] = ??? // Stream source genereating Messages based on backend event
val getSourceFiltered: Flow[Message, Message, _] = ??? // the outgoing Source should push Server event messages based on client's "Predicate" message
建立连接后,我希望用户通过以下过滤器发送:
{
productId: 1,
city: New York
}
然后服务器应该继续从后端(数据库)实时推送数据流(事件),并将更详细的产品信息返回给用户客户端:
{
orderId: 1122,
productId: 1,
productName: Coke,
vendor: ABC,
city: New York
timestamp: 2019-11-13 09:30:00
}
{
orderId: 3322,
productId: 1,
productName: Coke,
vendor: EFG,
city: New York
timestamp: 2019-11-13 09:31:00
}
...
Actor
是否绝对需要处理这个问题? 如果是这样,任何指导都会非常有帮助!
更新简而言之,如何根据用户的消息发出事件驱动的服务器推送源?
此外,也许我对如何构建新的Source[Message, _]
感到困惑? 我知道Flow
是不可变的,但应该是一种基于输入( Flow.fromSinkAndSource
?)的切换方式。 因为 Akka 只有指令 api 像: handleWebSocketMessages(flow: Flow[Message, Message, _])
它只消耗输入消息,但不产生新的Source
,而对于handleMessagesWithSinkSource(sink, source)
接收器和源没有与我的逻辑联系。 我仍在努力思考如何使它工作..
虽然不是很明显,但Flow[Message, Message, _]
足以实现大多数协议。 请记住, Flow
可以通过statefulMapConcat
或flatMapConcat
。 Flow
甚至可以在没有直接接收到要回复的输入的情况下通过诸如extrapolate
或merge
之类的功能与某些滴答声源开始发出内容。
在你的情况下:
val getSourceFiltered: Flow[Message, Message, _] = Flow[Message]
.take(1) // you only care about the first thing that the client sends
.flatMapConcat {
case TextMessage.Strict(txtMsg: String) =>
// Here is where you parse and make your filter using the message the client message
val clientFilter: Message => Boolean = makeFilter(txtMsg)
getSourceAll.filter(clientFilter)
case _ => Source.single(TextMessage("Expected a single strict JSON message"))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.