[翻譯]akka in action之akka-stream ( 3 使用Graph DSL實現扇入扇出 )
3 使用Graph DSL實現扇入扇出
到目前為止,我們只研究了一個輸入和一個輸出的線性處理。Akka-stream提供了用於描述扇入和扇出的圖DSL(領域專用語言),能夠定義有大量輸入和輸出的圖。圖形 DSL 差不多是一種圖解 ASCII-許多情況下, 你可以將圖形的白板圖轉換為 DSL。
有許多扇入和扇出GraphStages,可用於建立各種圖形,例如Source、FLow、Sink。也可以建立你自己的自定義GraphStages 。
你以使用圖形 DSL 建立任意Shape 的圖形。在akka-stream方面,Shape定義了圖有多少輸入和輸出(這些輸入和輸出稱作入口(Inlets) 和出口(Outlets))。在下面的例子中,我們將建立一個Flow-shaped 圖,所以它可用於像前面的POST路由。內部它使用了一個扇出形狀。
3.1 廣播到流
繼續上一章的例子,我們按照日誌事件的狀態將日誌事件進行拆分(一個Sink用於所有的錯誤,一個用於所有的警告,等等),以便每次對一個或多個狀態發出GET請求時,不必過濾這些事件。下圖展示了BroadcastGraphStage 如何將事件傳送到不同的流。
圖DSL提供了GraphDSL.Builder 來建立圖中的節點,並且 ~> 方法用於將節點連線在一起,很像via方法。圖中的節點是型別圖, 在引用圖的某個部分時可能會混淆, 因此在某些情況下, 我們將使用術語 "node"。
下面展示了程式碼中上圖如何定義。也展示了從圖開放入口和出口中定義一個流。
探究Graphs和Shapes
processStates返回型別可能不是你所期望的。不是Flow[Event, ByteString, NotUsed]型別,而是Graph[FlowShape[Event, ByteString], NotUsed]。事實上,Flow[-In, +Out, +Mat]繼承於Graph[FlowShape[In, Out], Mat]。這表示一個Flow僅僅是一個有預定義Shape的Graph。如果你稍微深入akka-stream原始碼,你會發現 FlowShape 是一個只有一個輸入和一個輸出的Shape。
所有預定義的元件定義的方法類似:所有都定義為帶有一個Shape的Graph。例如,Source和Sink分別繼承於 Graph[SourceShape[Out], Mat] 和Graph[SinkShape[In], Mat]。
引數builder是一個GraphDSL.Builder,它是可變的。它只打算在這裡使用匿名函式來建立一個圖。GraphDSL.Builder的add方法返回一個Shape,它描述了一個圖的入口和出口。
過濾流寫入到不同檔案,如logFileSink(logId, state) 方法呼叫所示。例如,對於檔案logId1的錯誤,將追加一個1-errors檔案。
在POST路由裡使用processStates:
src.via(processStates(logId))
.toMat(logFileSink(logId))(Keep.right)
.run()
用於返回錯誤日誌檔案的GET路由與普通的GET路由類似,除了一個命名約定(用於從[log-id]-error 檔案讀取)。
下一節,我們將看看合併源,以便可以返回合併在一起的所有日誌,或者僅是某日誌檔案所有狀態不是OK的日誌事件。
3.2 合併流
讓我們看看用於合併源的圖。在第一個例子中,我們合併了所有狀態不是OK的事件到一個檔案中。 對/logs/[log-id]/not-ok 進行GET將返回所有狀態不是OK的事件。下圖展示了MergeGraphStage 如何將三個Sources合併為一個。
下面的程式碼展示了MergeGraphStage 如何應用圖DSL。它定義了一個mergeNotOK方法,將特定 logId 的所有非OK日誌源合併到一個源中。
注意,warning, error 和 critical 源,首先通過了一個JSON幀化流,否則, 您可以讀取任意 ByteStrings 並將它們合併在一起, 從而導致 JSON 輸出出現亂碼。
三個源由帶有三個入口的MergeGraphStage 合併。SourceShape 由merge.out 出口建立。Source有一個fromGraph 方便方法,將帶有SourceShape 的Graph轉化為Source。
MergePreferred GraphStage
MergeGraphStage 從其任何輸入中隨機取元素。Akka-stream 還提供了一個 MergePreferredGraphStage, 它有一個輸出埠、一個首選輸入埠, 以及零個或多個次級埠。當其中一個輸入有可用的元素時, MergePreferred 會發出, 如果多個輸入有可用的元素, 則傾向於首選的輸入。
mergeNotOk 方法稍後用於getLogNotOkRoute 去建立讀取的Source,如下所示
def getLogNotOkRoute =
pathPrefix("logs" / Segment /"not-ok") { logId =>
pathEndOrSingleSlash {
get {
extractRequest { req =>
complete(Marshal(mergeNotOk(logId)).toResponseFor(req))
}
}
}
}
還有一個用於合併源的簡化 API, 我們將使用它來合併所有日誌。請求GET /logs 將返回所有合併在一起的日誌。下面程式碼展示瞭如何使用簡化的 API。
Source.combine 方法從多個源中建立Source,類似於使用圖形DSL進行的操作。mergeSources 用於合併具有相同型別任意數量的源。例如該方法用於/logs路由中,如下所示。
預定義和自定義GraphStages
在akka-stream 中有相當多的預定義 GraphStages, 這裡沒有展示負載平衡 (-Balance)、壓縮 (Zip、ZipWith) 和串聯流 (Concat) 等等。這些圖的DSL非常類似於已經展示的示例。在所有情況下, 都需要向生成器新增節點,連線形狀的入口和出口(由add方法返回),然後從函式返回某個形狀,並將其傳遞給Graph.create 方法。也可以編寫自己的自定義 GraphStage, 這超出了akka-stream的介紹性章節的範圍。
本節中展示的 BroadcastGraphStage 在任何輸出應用背壓時都應用背壓, 這意味著您只能以最慢的使用者可以讀取的速度進行廣播。下一節將討論如何使用緩衝來允許生產者和消費者以不同的速度執行, 以及如何在不同速度下執行的生產者和消費者之間進行調解。
相關文章
- Flume與Kafka整合--扇入、扇出功能整合,其中扇出包括:複製流、複用流Kafka
- Akka Stream文件翻譯:Motivation
- Akka官方文件翻譯:Cluster Specification
- 使用Akka實現Reactive DDDReact
- akka-typed(4) - EventSourcedBehavior in action
- [翻譯] 使用JavaScript實現自己的PromisesJavaScriptPromise
- Akka Stream文件翻譯:Quick Start Guide: Reactive TweetsGUIIDEReact
- 使用Akka實現CQRS/ES的原始碼原始碼
- Kotlin 中使用 DSL 實現建造者模式Kotlin模式
- LoadRunner函式中文翻譯系列之一--Action函式
- 使用 FastGPT 實現最佳 AI 翻譯工作流:全世界最信達雅的翻譯ASTGPTAI
- 蝴蝶書-task2: 文字推理、摘要、糾錯 transformers實現翻譯 OpenAI翻譯 PyDeepLX翻譯 DeepLpro翻譯ORMOpenAI
- Akka系列(九):Akka分散式之Akka Remote分散式REM
- Akka 系列(九):Akka 分散式之 Akka Remote分散式REM
- [翻譯 EF Core in Action 2.4] 載入相關資料
- (三)struts2進階之實現Action
- 用Scala和Akka實現DDD
- Guava翻譯之SmallFunctionGuavaFunction
- [譯] 使用 Flutter 製作 3D 翻轉動畫Flutter3D動畫
- docker官方文件翻譯3Docker
- 語音翻譯軟體怎麼用?怎麼實現語音的翻譯
- [翻譯] 在JavaScript中使用weakmaps實現私有例項成員JavaScript
- Go 語言實現解析器翻譯Go
- 非同步架構思維:使用Akka實現領域建模非同步架構
- 基於Python的Akka實現Python
- Akka 系列(七):Actor 持久化之 Akka persistence持久化
- guava翻譯系列之JoinerGuava
- guava翻譯系列之SplitterGuava
- Guava文件翻譯之 ServiceGuava
- Guava文件翻譯之ListenableFutureGuava
- 教你如何利用C#呼叫百度翻譯API實現一個翻譯功能C#API
- ul>li*3 實現翻書動畫效果動畫
- 使用google翻譯 api 翻譯中文成其他語言GoAPI
- 記一次翻譯工具的開發-有了它,實現實時翻譯還遠嗎?
- A3C論文翻譯
- 3 Java NIO Buffer-翻譯Java
- Understand Lambda Expressions in 3 minutes(翻譯)Express
- [Flutter翻譯]使用Flutter WEB實現桌面GUI(第2部分:Dock)FlutterWebGUI