2013-06-29 68 views
4

请注意,以下描述仅用于说明目的。问题是关于akka中事件流处理的模式,而不是关于如何用替代设计来解释说明性示例的问题。当路易斯想要更改路由时,Akka路由演员

想象一下,在Akka中编写的复杂事件处理引擎,其中事件规则由参与者建模。消息的事件流与订单类似,订单中的物品履行,订单付款。业务规则参与者正在做类似的事情,即向客户开具发票并跟踪付款,直至完成。业务规则感兴趣的数据本质上是非常动态的,因为不可能知道哪些规则正在跟踪消息流的哪些部分。

天真地可以使用boardcast路由器风格的方法。所有业务规则参与者都会看到所有数据,如果它们不是跟踪数据,他们会忽略该消息。然而,这会产生可扩展性问题,因为并非所有规则参与者都对所有数据感兴趣的比例非常高。这意味着使用一个索引,其中规则actor通过消息中的复杂业务标识符来跟踪哪些类型的消息。那么我们只能向规则演员发送他们正在寻找的数据。这个消息的索引指向哪些参与者响应演员中的业务规则而改变。从路由参与者的角度来看,这个路由器想要动态地改变路由。

这会引起计时问题。如果路由参与者的运行速度足够快,以保持许多路由器忙碌,那么它将传递消息流,例如{A,B,C},直到某个特定路由器获得消息{A}。如果那个被告人决定它需要消息{B},那么它将已经被路由到它的上游,但是不会被路由到最近发现它现在想要消息{B}看到消息{A}的被告的邮箱。修改后的路由只会在{C}之后的消息中生效,或者当路由参与者处理来自特定的路由器的响应消息时可能会更晚。

解决此问题的一个办法是缓存路由参与者的消息。然后,如果一个路由器改变了它对响应消息的兴趣,那么路由参与者可以扫描旧消息的缓冲区并根据需要重新发送一些消息。这意味着需要很多代码来保持消息的缓冲区尽可能小,以便能够尽可能高效地重发它们。我想知道是否有更标准的模式或更自然的方法来解决阿卡内的动态路由问题?

[脚注:在注释中描述的替代解决方案是使用消息缓存并让规则参与者击中缓存,但让我们假设缓存将非常大,迫使IO或主阶段jdbc存储所以假设缓存不可取,如果可以避免的话。问题是关于akka中的事件流模式,其中路由规则可以以高度动态的方式改变 - 上述系统的近似描述被简化并且仅用于说明目的。关键的参数是关于消息流{A,B,C}并且具有路由读取{A}决定它然后需要已经由上游路由器调度的消息{B}。]

+0

问题是否每个要处理的事件/消息都有一个ID并且您的应用程序可以明确说出我有消息ID = A我需要消息ID = B吗?根据您当前的设计,或许您有一个聚合器,它可以维护一个ID列表并知道潜在的副作用,并在需要时将消息转发给其他参与者。另一种选择是尝试尽可能多地分组您的管道线,这样您就可以向最少数量的参与者进行广播,并且演员链会自行决定接下来发送消息的位置。 – NightWolf

+0

@NowWolf新的akka​​软件是一个聚合器,它的工作是制定业务规则来确定哪些消息是相关的,并根据这些消息采取行动。因此,在将问题发送给规则参与者之前,无法简化该问题以了解哪些消息是相关的。事件的峰值爆发量将非常高,因此需要扇出管道。路由参与者应该掌握哪些规则通过消息的哪些业务密​​钥跟踪哪些消息的索引。那么挑战就像问题中所概括的那样:如何有效地让路线更新那个指数。 – simbo1905

+0

林不知道我完全理解为什么你需要有一个路由的演员。这听起来像RuleActorX正在决定路由状态需要改变。对我来说这听起来像是丰富。如果RuleActorX决定它需要更多的数据,那么它应该通过向某个重新路由器发送消息或明确从存储中获取消息来请求。也许你可以使用代理来管理状态变化,而不是缓冲看起来有风险的消息。 – NightWolf

回答

0

这个问题似乎相当一般。我在这里看到两个子问题

  1. 它可能受益于规则分解。如果有可能创建一个“关联标记”(客户id,初始命令id),那么一些中间参与者可以做很好的初始路由(例如基于标记的散列)。最后,终极演员可以从更小的一组消息中选择需要的东西。

  2. 对于构建具有复杂规则的通用事件处理拓扑,可以考虑一个库SynapseGrid。它有一个构建拓扑的构建器,然后转换为相互关联的参与者的运行时系统。规则或者像Scala函数一样简单,或者像嵌套actor一样复杂。