不允许使用Akka Stream OnNext

时间:2015-06-18 16:20:22

标签: akka apache-kafka reactive-programming akka-stream

我刚刚关注了akka流的ActorPublisher示例,有时我收到了这条消息:

  

java.lang.IllegalStateException:当流不允许onNext   没有请求元素,totalDemand为0

查看文档,他们解释说:

  

通过调用onNext将元素发送到流。你被允许   发送与流订户请求的元素一样多的元素。   可以使用totalDemand查询此金额。它只允许   当isActive和totalDemand> 0时使用onNext,否则onNext将   抛出IllegalStateException。

     

当流订阅者请求更多元素时   ActorPublisherMessage.Request消息被传递给这个actor,并且   你可以采取行动。 totalDemand会自动更新。

如何防止totalDemand为零?当我收到此错误时,我丢失了我试图发送的消息。

以下是我一直关注的例子:

http://doc.akka.io/docs/akka-stream-and-http-experimental/1.0-RC3/scala/stream-integrations.html

这是我的班级考试

object Test extends App {

  implicit val actorSystem = ActorSystem("ReactiveKafka")
  implicit val materializer = ActorFlowMaterializer()

  val kafka = new ReactiveKafka(host = "localhost:9092", zooKeeperHost = "localhost:2181")
  val publisher = kafka.consume("test", "groupName", new StringDecoder())

  val workerActor = actorSystem.actorOf(Props[Worker], name = "workerActor")

  Source(publisher).map(WorkerPool.Msg(_, workerActor)).runWith(Sink.actorSubscriber(WorkerPool.props))

}

好吧,我收到了来自kafka的消息,我正在传递给WorkerActor,但是当向Kafka发送10条消息/秒时,其中一些因为这个错误而丢失。

更新

我遇到了这里描述的错误(使用相同的库):

https://github.com/softwaremill/reactive-kafka/issues/11

我使用缓冲区解决了我的问题,但看起来PR会解决这个问题。

https://github.com/softwaremill/reactive-kafka/pull/13

1 个答案:

答案 0 :(得分:2)

如果下游接收器没有任何需求,那么您唯一的选择是

  1. 告诉数据源提供Worker没有需求,以便源可以停止生成消息,直到有更多需求出现(反应性解决方案)。
  2. 缓冲消息,直到您从接收器获得一些需求,这可能会填满您的缓冲区并且您仍然会丢弃消息。
  3. 在需求为0时删除消息(这似乎是您当前的实现)。
  4. 但“背压”的全部意义在于防止在没有需求时调用onNext。

    要实现上面的buffering选项,您可以在Actor内部或外部缓冲:

    • 内部缓冲区:查看documentation中的“ActorPublisher”示例,了解在提供ActorPublisher的Actor中缓冲的示例。
    • 外部缓冲区:使用缓冲的材料化程序或流中的Flow.buffer使用外部缓冲区。