[英]Ask vs Tell or forward for Actors using Akka Streams
嗨,我有工作akka streams
沿akka-stream-kafka
。 我正在使用以下設置來設置流:
Source (Kafka) --> | Akka Actor Flow | --> Sink (MongoDB)
Actor Flow
基本上由將處理數據的Actor組成,以下是層次結構:
System
|
Master Actor
/ \
URLTypeHandler SerializedTypeHandler
/ \ |
Type1Handler Type2Handler SomeOtherHandler
因此,Kafka收到了一條消息,我寫出使用者並在atMostOnceSource
配置中運行它並使用
Consumer.Control control =
Consumer.atMostOnceSource(consumerSettings, Subscriptions.topics(TOPIC))
.mapAsyncUnordered(10, record -> processAccessLog(rootHandler, record.value()))
.to(Sink.foreach(it -> System.out.println("FinalReturnedString--> " + it)))
.run(materializer);
我最初使用打印作為接收器,只是為了使流程正常運行。
並且processAccessLog
定義為:
private static CompletionStage<String> processAccessLog(ActorRef handler, byte[] value) {
handler.tell(value, ActorRef.noSender());
return CompletableFuture.completedFuture("");
}
現在,根據定義,在演員期望響應時必須使用ask
,在這種情況下是有道理的,因為我想返回要寫入接收器中的值。
但是,每個人(包括文檔),何況避免ask
及,而使用tell
和forward
,一個驚人的博客上寫不要問,告訴 。
他在博客中提到,如果角色嵌套,則對第一條消息使用tell
,然后對消息使用forward
到達目的地,然后在處理后直接將消息發送回根actor。
現在這是問題所在
ask
仍然是正確的模式
從鏈接的博客文章中, ask
一個“缺點”是:
阻止一個actor本身,直到響應到達並完成處理之前,actor不能選擇任何新消息。
但是,在akka-stream
這正是我們正在尋找的確切功能,也稱為“背壓”。 如果Flow
或Sink
器需要很長時間來處理數據,那么我們希望Source
速度變慢。
作為附帶說明,我認為博客文章中聲稱附加的偵聽器Actor
導致實現“數十倍重”的實現是誇張的。 顯然,一個中間Actor增加了一些延遲開銷,但沒有增加12x
。
消除背壓
您所尋找的任何實現都可以有效消除背壓。 無論您的處理邏輯是否在處理程序Actors中以與Source生成數據相同的速度完成計算,僅使用tell
的中間Flow會將需求連續傳播回Source。 舉一個極端的例子:如果您的Source每秒可以產生100萬條消息,但是通過tell
接收到這些消息的Actor每秒只能處理1條消息,該怎么辦? 那個Actor的郵箱會怎樣?
通過在中間Flow中使用Ask模式,您可以有目的地鏈接處理程序的速度和Source生成數據的速度。
如果您願意刪除從接收器到源的反壓信號,那么您最好不要使用akka流。 您可以具有反壓力消息或無阻塞消息,但不能同時具有兩者。
拉蒙·J·羅梅羅和維吉爾是對的,但我會盡力擴大答復。
1)我認為“不要問,說”教條主要用於Actor系統架構。 在這里,您需要返回一個Future,以便流可以解析處理后的結果,您有兩個選擇:
getSender
方法,以便D可以將響應發送給A)。 無法在消息中發送“承諾”或“未來”(不可序列化),因此無法避免創建這種短暫的演員。 最后,您所做的幾乎都是相同的...
2)使用空的Sink結束流是完全可以的(實際上akka提供了Sink.ignore()
方法)。
似乎您缺少使用流的原因,它們是很酷的抽象,可提供可組合性,並發性和背壓。 另一方面,演員無法構成,很難應對背壓。 如果您不需要此功能,並且演員可以輕松完成工作,則不應首先使用Akka流。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.