【问题标题】:Akka: How to ensure that message has been received?Akka:如何确保消息已经收到?
【发布时间】:2015-09-04 04:08:41
【问题描述】:

我有一个演员 Dispenser。它的作用就是它

  1. 按要求分配一些对象
  2. 聆听新的到来

代码如下

class Dispenser extends Actor {
    override def receive: Receive = {
        case Get =>
            context.sender ! getObj()
        case x: SomeType =>
            addObj(x)
    }
}

在实际处理中,从发送新对象到分发器开始分发它是否经过 1 毫秒甚至几秒钟都没有关系,因此没有代码跟踪它。

但现在我正在为分配器编写测试,我想确保它首先收到新对象,然后才收到 Get 请求。

这是我想出的测试代码:

val dispenser = system.actorOf(Props.create(classOf[Dispenser]))
dispenser ! obj
Thread.sleep(100)
val task = dispenser ? Get()
val result = Await.result(task, timeout)
check(result)

它满足一项重要要求 - 它不会更改原始代码。但它是

  1. 即使在非常高性能的机器上也至少慢 100 毫秒
  2. 不稳定且有时会失败,因为 100 ms 或任何其他常量不提供任何保证。

问题是如何进行满足要求且没有上述缺点的测试(没有任何其他明显的缺点)

【问题讨论】:

  • 您可能必须将测试参数化:将睡眠时间更改为 1 毫秒,然后运行很多次。如果它在 > 92% 的时间内工作,则测试通过。 92% 是我凭空得出的一个数字。选择您的号码并满意。
  • 我不认为在 8%(甚至 0.01%)的情况下终止部署过程(包括运行自动化测试)是进行测试的正确方法。所以我更喜欢不涉及统计的解决方案
  • 在 akka 的第一个版本中,有一个基于邮箱大小的解决方案。对于 akka2,此功能已禁用。但是邮箱仍然可以自己实现。但是否存在更简单、更直观的解决方案?
  • @Daenyth 感谢您的链接。我对类似于询问模式的解决方案持开放态度,在成功交付的情况下一切正常,在其他情况下,它等待的时间不超过给定的超时时间。

标签: multithreading scala akka actor


【解决方案1】:

您可以取出Thread.sleep(..),您的测试就可以了。 Akka 保证您需要的订购。

有代码

dispenser ! obj
val task = dispenser ? Get()

dispenser 将在Get 之前处理obj,因为

  1. 同一线程将obj 然后Get 放入演员的邮箱,因此它们在演员邮箱中的顺序正确
  2. Actor 按顺序一次处理一条消息,因此这两条消息将被 Actor 接收并按照它们在邮箱中的排队顺序进行处理。

(..如果您的示例代码中没有其他内容 - 路由器,getObj 或 addObj 中的异步处理,存储,..)

【讨论】:

  • 这不是真的。订购保证仅适用于以“一劳永逸”方式发送的消息。使用 ask 模式时,消息会避开邮箱并直接到达目的地,因此不保证 obj 和 Get() 顺序。
  • .ask() 的请求只是.tell() - 查看ask() impl in the source
  • 首先,由于documentationask 操作涉及创建内部参与者。其次,顺序确实发生了变化(甚至经常发生)。
  • 内部参与者是接收响应 - 请求是通过调用线程中的.tell。你查看AskSupport 源代码了吗?
  • 如果你使用的是akka testkit,你可以使用tell Obj,tell Get,然后是expectMsg。这将保证消息的顺序。
【解决方案2】:

Akka FSM 模块对于测试参与者的底层状态和行为非常方便,并且不需要专门为测试更改其实现。 通过使用 TestFSMRef,可以通过以下方式获取参与者的当前状态和数据:

val testActor = TestFSMRef(<actors constructor or Props>)
testActor.stateName shouldBe <state name>
testActor.stateData shouldBe <state data>

http://doc.akka.io/docs/akka/2.4.1/scala/fsm.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-15
    • 2018-01-19
    • 2020-08-30
    • 2013-11-29
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 2015-12-14
    相关资源
    最近更新 更多