【发布时间】:2015-03-18 15:49:20
【问题描述】:
我们正在为每个(小)传入消息组创建一个参与者链,以保证它们的顺序处理和管道(组通过公共 ID 进行区分)。问题是我们的链有分叉,比如A1 -> (A2 -> A3 | A4 -> A5),我们应该保证通过A2 -> A3 和A4 -> A5 的消息之间没有竞争。当前的遗留解决方案是阻止A1actor 直到当前消息被完全处理(在子链之一中):
def receive { //pseudocode
case x => ...
val f = A2orA4 ? msg
Await.complete(f, timeout)
}
因此,应用程序中的线程数与正在处理的消息数成正比,无论这些消息是活动的还是只是异步等待外部服务的某些响应。它与 fork-join(或任何其他动态)池一起工作大约两年,但当然不能与固定池一起使用,并且在高负载的情况下会极大地降低性能。不仅如此,它还会影响 GC,因为每个被阻塞的 fork-actor 都在内部保存了冗余的先前消息的状态。
即使有背压,它创建的线程数也比收到的消息多 N 倍(因为流中有 N 个顺序分叉),这仍然很糟糕,因为处理一条消息需要很长时间但 CPU 不多。所以我们应该处理尽可能多的消息,因为我们有足够的内存。我想出的第一个解决方案 - 像A1 -> A2 -> A3 -> A4 -> A5 这样线性化链。有没有更好的?
【问题讨论】:
标签: multithreading scala akka future