![](/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.