如果下游仍在工作,如何在Akka流中为下游丢弃消息

时间:2020-04-16 12:26:20

标签: scala akka-stream

如果下游仍在处理前一条消息,则需要将所有传入消息从上游放到下游。我试图通过限制缓冲区来做到这一点,但没有成功。我该如何实现?

这是我简单的例子

import akka.actor.{Actor, ActorSystem, Props}
import akka.stream.{ActorMaterializer, OverflowStrategy}
import akka.stream.scaladsl.{Flow, Sink, Source}

import scala.concurrent.duration._

object Test extends App {

  implicit val system = ActorSystem("System")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = system.dispatcher

  val (actor, actorSource) = Source.actorRef[Int](bufferSize = 0, OverflowStrategy.dropBuffer).preMaterialize()

  class ActualScheduledActor extends Actor {

    var idx: Int = 0

    override def receive: Receive = {
      case _: Int =>
        idx = idx + 1
        if (idx < 6) {
          println(s"sending $idx")
          actor ! idx
        }
    }
  }

  val flow = Flow[Int].map { v =>
    println(s"$v: Going to sleep.")
    Thread.sleep(5000)
    println(s"$v: Awake.")
    v
  }

  val scheduledActor = system.actorOf(Props(new ActualScheduledActor))
  system.scheduler.schedule(0.second, 1.second, scheduledActor, 0)

  actorSource
    .buffer(1, OverflowStrategy.dropBuffer)
    .via(flow)
    .runWith(Sink.ignore)
}

在此示例中,我使用ActualScheduledActor只是为了说明消息并未丢失并且似乎已被缓冲。这是输出:

sending 1
1: Going to sleep.
sending 2
sending 3
sending 4
sending 5
1: Awake.
2: Going to sleep.
2: Awake.
3: Going to sleep.
3: Awake.
4: Going to sleep.
4: Awake.
5: Going to sleep.
5: Awake.

1 个答案:

答案 0 :(得分:0)

它确实会删除邮件,您只是没有发送足够的邮件。

请根据您的要求修改此代码。

object AkkaStreamDropMessage extends App {
  import akka.actor.{Actor, ActorSystem, Props}
  import akka.stream.OverflowStrategy
  import akka.stream.scaladsl.{Flow, Sink, Source}

  import scala.concurrent.duration._

  implicit val system = ActorSystem("System")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = system.dispatcher

  val (actor, actorSource) = Source
    .actorRef[Int](bufferSize = 0, OverflowStrategy.dropBuffer)
    .preMaterialize()

  class ActualScheduledActor extends Actor {

    var idx: Int = 0

    override def receive: Receive = {
      case _: Int =>
        idx = idx + 1
        if (idx < 600) {
//          println(s"sending $idx")
          actor ! idx
        }
    }
  }

  val flow = Flow[Int].map { v =>
    println(s"GOT: $v")
    Thread.sleep(100)
    v
  }

  val scheduledActor = system.actorOf(Props(new ActualScheduledActor))
  system.scheduler.schedule(0.second, 50.millis, scheduledActor, 0)

  actorSource
    .buffer(1, OverflowStrategy.dropBuffer)
    .via(flow)
    .runWith(Sink.ignore)
}

它最终停止接收序列号

GOT: 34
GOT: 35
GOT: 36
GOT: 37
GOT: 38
GOT: 39
GOT: 49

在我的运行中,它从600个元素中删除了大约300个元素。

我认为(但我可能错了),它与为每个阶段定义的其他内部缓冲区有关,因此必须在实际的“丢弃”可见之前填充它们。

相关问题