Erlang 在使用Akka构建程序时,如何避免到处传递原始消息?

Erlang 在使用Akka构建程序时,如何避免到处传递原始消息?,erlang,akka,Erlang,Akka,我正在使用Akka构建我的运行时消息系统。但是它经常会遇到尴尬的情况:许多消息都是用并且很难跟踪业务逻辑。 根据Erlang中的编程手册,建议不要向其他人公开消息,而是使用函数封装actor消息,并使用导出([func1/1])或其他方法导出它 那么,是否可以在Akka中使用函数调用模式? 在使用Akka构建大型系统时,您如何阅读包含如此多消息的代码?新的实验性Akka类型支持在帮助理解和跟踪业务逻辑方面有很大帮助: 这样做的目的是允许您对协议进行编码,以便与类型系统中的参与者对话,这可以使您

我正在使用Akka构建我的运行时消息系统。但是它经常会遇到尴尬的情况:许多消息都是用
并且很难跟踪业务逻辑。
根据Erlang中的
编程手册
,建议不要向其他人公开消息,而是使用函数封装actor消息,并使用
导出([func1/1])
或其他方法导出它

那么,是否可以在Akka中使用函数调用模式?

在使用Akka构建大型系统时,您如何阅读包含如此多消息的代码?

新的实验性Akka类型支持在帮助理解和跟踪业务逻辑方面有很大帮助:

这样做的目的是允许您对协议进行编码,以便与类型系统中的参与者对话,这可以使您在阅读代码时更容易理解系统的工作方式

另一种选择是使用肉桂(一个Lightbend商业库)来跟踪消息,这可以让您了解运行时的控制流。下面是一篇关于它的博文:

如果你对你的演员做了很多要求,一个常见的模式是将其放在返回未来的方法后面。例如:

class MyService(actor: ActorRef) {
  def doSomething(msg: Something): Future[Result] = {
    (actor ? msg).mapTo[Result]
  }
}
当然,除了返回类型将是
Unit
之外,您可以将相同的内容应用于常规通知

最后,Akka中的一个常见模式是将所有消息类放在参与者的同伴对象中:

object MyActor {
  /** This message does something */
  case class MessageOne(foo: String)
  /** This message does something else */
  case class MessageTwo(bar: String)
}
class MyActor extends Actor {
  import MyActor._
  override def receive = {
    case MessageOne(foo) =>
      ...
    case MessageTwo(bar) =>
      ...
   }
 }
虽然这可能无助于遵循业务逻辑,但它确实使系统新手更容易通过将所有消息(带文档)放在一个地方来了解如何与参与者对话


还有一个关于构建代码的词——参与者应该对定义良好的协议承担有限的责任。一个设计良好的基于Akka的系统不需要你同时理解所有地方的信息流,它应该直接对每个参与者进行单独的推理。仔细使用参与者层次结构来提取子进程作为子参与者,在这方面确实有帮助。换句话说,如果为了了解系统的运行方式,您需要了解数百个参与者之间的数千条消息是如何流动的,那么您肯定存在设计问题,并且需要重新思考如何将参与者分解为独立的单元,这些单元可以像构建块一样轻松地组合在一起。

您可以做Erlang所做的事情,并隐藏所有传递到函数后面的消息。或者换句话说,您不应该处理参与者,而应该处理一般(域抽象)类,并且只将参与者用作底层实现

case class Cat(name: String)


trait Shelter {
  def leave(cat: Cat): Unit
}


class ActorShelter extends Shelter with Actor {

  var cats = List[Cat]()

  def leave(cat: Cat) =
    this.self ! cat

  def receive = {
    case cat: Cat =>
      cats = cat :: cats
  }
}
这将允许您在代码中使用
避难所
,而不必知道它是参与者


当然,您仍然需要决定是否要在所有使用
的强制转换中返回
单位
,或者只参考您自己。如果您在通话中使用
返回
Future
,或者等待实际值。

肯定有比这更好的系统。我是说,是阿克卡。Erlang一直存在,而且。。。真的吗?很好的建议!稍微考虑一下在对象中放置mesaage可能并不总是很好的解决方法。例如,如果我有一个case类消息需要在两个或多个actor定义中使用。此外,我认为类型化actor有其局限性,因为我们不能保证收到的所有消息都是类型良好的,它属于actor所做的。直接但有效,但问题是当我创建
ActorShelter
时,我只得到
ActorRef
类型。我怎样才能得到庇护所呢?这是一个很好的观点,而且稍微复杂一点。在Erlang中,您只需生成一个新的进程/参与者,而在Akka中,您必须在某些上下文(系统或其他现有参与者)中进行此操作。它可以根据您如何构造应用程序而有所不同,因此没有一种适合所有应用程序的解决方案。我会尝试进一步调查,也许会更新我的答案。谢谢你能花点时间解决这个问题。期待您的最新调查。