【问题标题】:order of events when using akka streams使用 akka 流时的事件顺序
【发布时间】:2018-04-24 13:20:15
【问题描述】:

阅读 akka-streams 的文档后,我不太清楚消息的顺序以及是否可以强制执行之类的事情。让我用我为聊天服务器编写的一小段代码来设置我的问题的上下文。

def flowShape(user: User) = GraphDSL
  .create(Source.actorRef[ChatMessage](bufferSize = 5, OverflowStrategy.fail)) {
    implicit builder =>
      implicit chatSource =>

      import GraphDSL.Implicits._

      val messageFromOutside = builder.add(Flow[String].map {
        case msg: String => UserTextMessage(user, msg)
        case _ => InvalidMessage
      })

      val merge = builder.add(Merge[ChatMessage](2))
      // UPDATE --> this is where the change comes
      // val merge = builder.add(Concat[ChatMessage](2))

      // val channelActorSink = Sink.actorRefWithAck(channelActor, ActorInitMessage, AckMessage, UserLeft(user))
      val channelActorSink = Sink.actorRef(channelActor, UserLeft(user))

      val actorAsSource = builder.materializedValue.map { actor => UserJoined(user, actor) }

      actorAsSource ~> merge.in(0)
      messageFromOutside.out ~> merge.in(1)
      merge ~> channelActorSink

      FlowShape(messageFromOutside.in, chatSource.out)
}

为了让我自己更简单,我将这个流形状与一个非常简单的源和汇一起使用。像这样的——

val source = Source(List[String]("hi", "hello", "what are you upto", "this is nice"))
val sink = Sink.foreach[ChatMessage] {
  case tm: UserTextMessage => println(s"${tm.user.username} :: ${tm.content}")
  case ul: UserLeft => println(s"${ul.user.username} just left the channel")
  case uj: UserJoined => println(s"${uj.user.username} just joined the channel")
  case _ => println(s"do not know what I just received")
}

val mychatchannel = new Channel(420, myactorsystem)

source.via(mychatchannel.chatFlow(User("sushruta"))).runWith(sink)

现在,我的担忧来了。在终端中打印的事件顺序根本不对。而且我不确定如何解决它。这是我得到的输出--

[INFO] [11/10/2017 17:42:20.431] [akka-streams-akka.actor.default-dispatcher-5] [akka://akka-streams/user/channel-actor-420] sushruta sent a message
[INFO] [11/10/2017 17:42:20.441] [akka-streams-akka.actor.default-dispatcher-5] [akka://akka-streams/user/channel-actor-420] received a user joined message
[INFO] [11/10/2017 17:42:20.443] [akka-streams-akka.actor.default-dispatcher-5] [akka://akka-streams/user/channel-actor-420] sushruta sent a message
[INFO] [11/10/2017 17:42:20.444] [akka-streams-akka.actor.default-dispatcher-5] [akka://akka-streams/user/channel-actor-420] sushruta sent a message

输出中缺少第一条消息hihi 消息似乎是在 UserJoin message 打印之前发送的。

我尝试使用actorRefWithAck(我在上面的代码中注释掉)来修复它(并在消息传递方面增加一些安全性)。它给出了类似的输出。

[INFO] [11/11/2017 06:33:03.731] [akka-streams-akka.actor.default-dispatcher-3] [akka://akka-streams/user/channel-actor-420] channel initialized and ready to take events
[INFO] [11/11/2017 06:33:03.735] [akka-streams-akka.actor.default-dispatcher-3] [akka://akka-streams/user/channel-actor-420] sushruta sent a message
[INFO] [11/11/2017 06:33:03.736] [akka-streams-akka.actor.default-dispatcher-3] [akka://akka-streams/user/channel-actor-420] received a user joined message
[INFO] [11/11/2017 06:33:03.737] [akka-streams-akka.actor.default-dispatcher-4] [akka://akka-streams/user/channel-actor-420] sushruta sent a message
[INFO] [11/11/2017 06:33:03.737] [akka-streams-akka.actor.default-dispatcher-3] [akka://akka-streams/user/channel-actor-420] sushruta sent a message
[INFO] [11/11/2017 06:33:03.738] [akka-streams-akka.actor.default-dispatcher-3] [akka://akka-streams/user/channel-actor-420] sushruta sent a message
[INFO] [11/11/2017 06:33:03.738] [akka-streams-akka.actor.default-dispatcher-3] [akka://akka-streams/user/channel-actor-420] received a UserLeft message

显然,似乎正在发生的事情是源在发送UserJoin 消息之前发送消息。我怎样才能解决这个问题?从概念上讲,我想我希望在源实现但在它实际发送第一条消息之前立即发送UserJoin message。这可能吗?

谢谢

【问题讨论】:

    标签: scala akka-stream akka-actor


    【解决方案1】:

    把溪流想象成水管:有水的时候,它就会流动。合并运算符不关心来自哪一侧的元素。如果您想订购这些输入,则需要使用 Concat 将其告知 Akka。

    【讨论】:

    • 非常感谢。这帮助了我并最终解决了这个问题。
    猜你喜欢
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 2016-11-09
    • 2012-03-26
    • 2018-09-29
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多