簡體   English   中英

使用Akka Streams詢問與講述或轉發演員

[英]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及,而使用tellforward ,一個驚人的博客上寫不要問,告訴

他在博客中提到,如果角色嵌套,則對第一條消息使用tell ,然后對消息使用forward到達目的地,然后在處理后直接將消息發送回根actor。

從博客

現在這是問題所在

  1. 如何將消息從D發送回A,這樣我仍然可以使用接收器。
  2. 擁有開放式流是一種好習慣嗎? 例如,在Sink無關緊要的流上播放,因為演員已經完成了工作。 (我不建議這樣做,這似乎是有缺陷的)。

ask仍然是正確的模式

從鏈接的博客文章中, ask一個“缺點”是:

阻止一個actor本身,直到響應到達並完成處理之前,actor不能選擇任何新消息。

但是,在akka-stream這正是我們正在尋找的確切功能,也稱為“背壓”。 如果FlowSink器需要很長時間來處理數據,那么我們希望Source速度變慢。

作為附帶說明,我認為博客文章中聲稱附加的偵聽器Actor導致實現“數十倍重”的實現是誇張的。 顯然,一個中間Actor增加了一些延遲開銷,但沒有增加12x

消除背壓

您所尋找的任何實現都可以有效消除背壓。 無論您的處理邏輯是否在處理程序Actors中以與Source生成數據相同的速度完成計算,僅使用tell的中間Flow會將需求連續傳播回Source。 舉一個極端的例子:如果您的Source每秒可以產生100萬條消息,但是通過tell接收到這些消息的Actor每秒只能處理1條消息,該怎么辦? 那個Actor的郵箱會怎樣?

通過在中間Flow中使用Ask模式,您可以有目的地鏈接處理程序的速度和Source生成數據的速度。

如果您願意刪除從接收器到源的反壓信號,那么您最好不要使用akka流。 您可以具有反壓力消息或無阻塞消息,但不能同時具有兩者。

拉蒙·J·羅梅羅和維吉爾是對的,但我會盡力擴大答復。

1)我認為“不要問,說”教條主要用於Actor系統架構。 在這里,您需要返回一個Future,以便流可以解析處理后的結果,您有兩個選擇:

  • 使用問
  • 為每個事件創建一個actor並將其傳遞給Promise,以便當該actor接收數據時,Future將完成(您可以使用getSender方法,以便D可以將響應發送給A)。 無法在消息中發送“承諾”或“未來”(不可序列化),因此無法避免創建這種短暫的演員。

最后,您所做的幾乎都是相同的...

2)使用空的Sink結束流是完全可以的(實際上akka提供了Sink.ignore()方法)。

似乎您缺少使用流的原因,它們是很酷的抽象,可提供可組合性,並發性和背壓。 另一方面,演員無法構成,很難應對背壓。 如果您不需要此功能,並且演員可以輕松完成工作,則不應首先使用Akka流。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM