因为我的第一个问题太长,所以我将其作为一个单独的问题提出。这是关于基于参与者的应用程序架构的另一篇文章。

跟踪应用程序中的消息路径

我们看一段Java代码:

public void deleteTrades(User user, Date date) {
    PermissionSet ps = permissionService.findPermissions(user)
    if (ps.hasPermission("delete")) {
        Set<Trade> ts = peristence.findTrades(date);
        reportService.sendCancelReports(ts);
        positionService.updateWithDeletedTrades(ts);
    }
}

在此代码中,我有 4 个独立的组件以及该过程所需的它们之间的交互 deleteTrades 是明确定义的。它完全包含在方法中 deleteTrades.

对此进行建模 Actor并用 4 个独立的参与者替换我的 4 个组件,我如何(在我的脑海中)跟踪程序涉及的内容?特别是如果我避免使用 !? 接线员,那么我可能会发送一条消息 ConditionalDelete 给我的 PermissionActor, ,这将发送一条消息 GetTradesAndDelete 给我的 PersistenceActor 然后将发送进一步的消息等。处理删除的代码将散布在我的应用程序中。

这也意味着几乎每个参与者都需要每个其他参与者的句柄(以便转发消息)。

正如我之前的问题,人们如何处理这个问题?有没有一个好的建模工具可以让您跟踪这一切?人们使用吗 !? 我是否将太多组件变成了 Actor是?

有帮助吗?

解决方案

您肯定使用了 5 个组件。有处理特定任务的演员,也有协调者。

当然,您必须遇到的问题是如何异步链接它。嗯,这实际上有点简单,但它可能会使代码变得模糊。基本上,您向每个组件发送您想要的回复。

react {
  case DeleteTrades(user,dates) => 
    PermissionService ! FindPermissions(user, DeleteTradesPermissions(dates) _)
  case DeleteTradesPermissions(dates)(ps) =>
    if (ps hasPermission "delete")
      Persistence ! FindTrades(date, DeleteTradesTradeSet _)
  case DeleteTradesTradeSet(ts) =>
    ReportService ! SendCancelReports(ts)
    PositionService ! UpdateWithDeletedTrades(ts)
}

在这里,我们使用柯里化来传递第一个返回答案中的“日期”。如果有很多与交互相关的参数,最好将所有正在进行的事务的信息保留在本地 HashSet 中,并仅传递一个令牌,您将在收到答案时使用该令牌来查找该信息。

请注意,这个单个参与者可以处理多个并发操作。在这种特殊情况下,只需删除事务,但您可以添加任意数量的不同操作以供其处理。当一项操作所需的数据准备就绪时,该操作就会继续。

编辑

以下是如何定义这些类的工作示例:

class Date
class User
class PermissionSet

abstract class Message
case class DeleteTradesPermission(date: Date)(ps: PermissionSet) extends Message
case class FindPermissions(u: User, r: (PermissionSet) => Message) extends Message

FindPermissions(new User, DeleteTradesPermission(new Date) _)

关于柯里化和函数的一些解释。班上 DeleteTradesPermission 被咖喱化,这样你就可以通过 Date 在它上面,并让一些其他功能完成它 PermissionSet. 。这将是应答消息的模式。

现在,班级 FindPermissions 接收一个函数作为第二个参数。接收此消息的参与者会将返回值传递给此函数,并会收到一个 Message 作为答案发送。在此示例中,消息将同时包含 Date, ,调用者发送的,以及 PermissionSet, ,这是应答演员提供的。

如果预计不会有答案,例如以下情况 DeleteTrades, SendCancelReportsUpdateWithDeletedTrades 出于本示例的目的,您不需要传递返回消息的函数。

由于我们期望有一个函数返回一个消息作为需要答案的消息的参数,因此我们可以定义如下特征:

trait MessageResponse1[-T1] extends Function1[T1, Message]
trait MessageResponse2[-T1, -T2] extends Function2[T1, T2, Message]
...

其他提示

演员不应被用来代替传统的服务组件,而不考虑。

大多数我们今天写的服务组件,通过培训,是无状态的。无状态的服务组件更容易管理(没有消息类等),比演员。其中之一,他们虽然缺少的东西,当比较的演员,是异步执行。但是,当客户期待的结果,同步返回的大部分时间,同步无状态的服务组件是蛮好的工作。

演员是当有来管理内部状态的良好配合。有没有必要做内部的任何同步“的行为()”来访问内部状态和担心竞争条件。只要 ”!?”没有内部“行为()”使用的,死锁应该被最小化,以及

演员应该警惕而处理消息做任何阻塞处理。由于演员处理他们的消息顺序,任何它们阻塞等待I / O内部时间“ACT()”,它们不能处理其邮箱中的任何其它消息。斯卡拉成语用在这里是启动另一个临时演员,做实际的阻塞操作。这种反模式影响基于事件的(反应)演员甚至更因为它阻止该线程基于事件的演员是捎带上为好。

据我所知,你的电话到服务组件的所有四个可能阻塞,所以管它应采取将它们转换为演员的时候,使他们的规模。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top