Akka Typed:回复来自不同参与者的消息(告诉)

vx6bjr1n  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(209)

使用Akka classic,可以轻松实现服务(作为参与者:ServiceActor),

  • 接收来自不同参与者的请求(即,不同类型的参与者:请求者A、请求者B等),
  • 处理该请求,
  • 向请求者发回确认。

请求者A向ServiceActor发送RequestMessage,ServiceActor向请求者A发回Acknowledgement
类似地,RequestorB向ServiceActor发送RequestMessage,ServiceActor向RequestorB发回Acknowledgement
无论请求是什么,都只有一种类型的RequestMessage和Acknowledgement,所有RequestMessage都由ServiceActor以相同的方式处理。
如何使用Akka Typed实现类似的功能?现在请求消息必须包含显式的replyTo:ActorRef[RequestorA.Message],有没有一种方法可以避免为每个请求者实现不同的RequestMessage?

  • RequestFromRequestorA(replyTo:ActorRef[请求者A.消息])
  • RequestFromRequestorB(replyTo:ActorRef[请求者B.消息])

类似地,有没有一种方法可以避免向每种类型的请求者发回不同类型的确认?

ftf50wuq

ftf50wuq1#

通常在Akka Typed中,响应消息由处理请求的Actor的协议定义,例如(在Scala中):

  1. object MyActor {
  2. sealed trait Command
  3. case class Request(replyTo: ActorRef[Response]) extends Command
  4. sealed trait Response
  5. // and so forth
  6. }

然后,发送Request的参与者有责任安排处理Response。如果发出请求的参与者只是为了发送请求而存在,它可以将自己定义为Behavior[Response],但在更一般的情况下,可以使用几种策略。
参与者可以设置消息适配器:

  1. val responseRef = context.messageAdapter { response =>
  2. // convert to this actor's message protocol
  3. ???
  4. }
  5. otherActor ! MyActor.Request(responseRef)

如果这样做,通常最好只设置一次responseRef(例如,以Behaviors.setup为单位)。
如果参与者只执行一次请求,或者只期望每个请求有一个响应(并且期望在有限的时间内得到响应),那么“ask模式”可能更清晰:

  1. implicit val timeout: Timeout = 15.seconds
  2. context.ask(otherActor, MyActor.Request(_)) {
  3. case Success(resp) =>
  4. // convert to this actor's message protocol
  5. ???
  6. case Failure(ex) =>
  7. // convert to this actor's message protocol
  8. ???

这确实需要您定义一个显式的超时,并处理没有及时收到响应的情况。注入到Request消息中的ActorRef是短暂的:它将不会接收到发送给它的第一消息之外的任何消息,也不会接收到超时之后的消息。
还可以将参与者的行为定义为Behavior[Any](类似于“经典”无类型参与者),但不将该事实暴露在参与者之外。在Scala中,这是相当简单和安全的,这要归功于逆变:

  1. Behaviors.setup[Any] { context =>
  2. // context.self is an ActorRef[Any], which by contravariance is usable as any type of ActorRef
  3. otherActor ! MyActor.Request(context.self)
  4. Behaviors.receiveMessage {
  5. case resp: MyActor.Response =>
  6. // handle response directly
  7. ???
  8. case _ =>
  9. Behaviors.unhandled
  10. }
  11. }.narrow[Command]

派生的ActorRef将是一个ActorRef[Command](即仅承诺处理Command),但参与者能够决定承诺处理它想要处理的任何消息(即使不是Command)。当这个参与者向它自己发送消息时,这确实会使你退出编译器的帮助;此外,这可能是一个有点模糊的模式,所以它的使用应该得到很好的注解。

展开查看全部

相关问题