我们有一个Scala Akka ActorSystem设置,每天处理数百万个事件,历史上我们很少发现1或2个事件被处理过两次,但最近重复事件在某些日子已经增加到大约100个。
我们的设置简化如下:
$notifications->load(['user' => function($query){
$query->select(["*"]
}]);
每个事件都有一个唯一的ID,在我们的日志中它显示一些事件已经被处理了两次(转到EventHandler.receive),彼此之间的毫秒数。所有演员都是本地人。
AFAIK默认的邮件传递可靠性至少是一次,这可能是因为越来越多的邮件似乎被多次传递,以及如何减少这个问题?
我们的系统设置为处理重复项,我们只是不知道为什么它最近似乎在增加,并希望减少它。
答案 0 :(得分:2)
假设您的系统没有生成具有相同ID的重复工作单元,系统有时会多次处理消息的可能原因是因为事件被分配给EventHandler
演员的方式;它与Akka的消息传递保证无关。
考虑您的getUnprocessEvents()
方法。它返回Future[Seq[Event]]
并在actor的常规消息处理之外运行,并且无法保证在再次调用m
之前从Seq
删除了消息getUnprocessEvents()
。消息被推送给工人,而不考虑他们是否可以进行更多工作。在后续呼叫m
时,工作人员仍然可以处理消息getUnprocessEvents()
,在这种情况下,m
将再次发送到工作人员的邮箱。使用调度程序定期调用此方法 - 即,指定一个时间窗口以努力为工作者提供足够的时间来处理他们的消息 - 是协调工作的一种有缺陷的方法。
更好的方法是使工作队列成为工作协调器actor状态的一部分(即,使队列成为actor中的内部变量,并通过actor消息传递来改变队列)并使用work pulling pattern。另外,请考虑使用Akka Streams。
作为旁注,EventJob
会创建一个新的ActorSystem
:
val EventListnerPoolOfActors = ActorSystem().actorOf(...)
每个应用程序应该只有一个ActorSystem
。请改用context
:
val EventListnerPoolOfActors = context.actorOf(...)