在开发一个相当大的 Akka 应用程序时,我在使用普通方法和非 Akka 类时遇到了一个非常简单的结构,但在使用 Akka 时实际上很难确定,这就是为什么我来这里问你什么建议是解决此问题的最佳方法。
所以问题是这样的,我有一个父角色,我们称他为“连接器”,连接器的行为描述了当它收到 ConnectCommand 实例时应该做什么。首先,它使用 HttpClient 提交表单,然后转到几个 URL 以检查某些会话参数,并最终向发送者(称为“消费者”)发送一条连接消息,其中包含使用 API 所需的所有内容。
现在,我非常喜欢讲述,而不是太多的拉/问,所以在我看来,实现这一点是一项艰巨的任务。让我们回顾一下。 HttpClientActor 返回的所有响应都是一个 Response 实例,因此首先想到的是在我的 actor 中定义多个行为,并在连接过程的某个步骤完成后逐步将行为更改为下一步。
private final PartialFunction<Object, BoxedUnit> inital = ReceiveBuilder
.match(ConnectCommand.class, c -> this.startConnection())
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage1 = ReceiveBuilder
.match(Response.class, this::stage1)
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage2 = ReceiveBuilder
.match(Response.class, this::stage2)
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage3 = ReceiveBuilder
.match(Response.class, this::stage3)
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage4 = ReceiveBuilder
.match(Response.class, this::stage4)
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage5 = ReceiveBuilder
.match(Response.class, this::stage5)
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage6 = ReceiveBuilder
.match(Response.class, this::stage6)
.matchAny(this::unhandled)
.build();
private final PartialFunction<Object, BoxedUnit> stage7 = ReceiveBuilder
.match(Response.class, this::stage7)
.matchAny(this::unhandled)
.build();
这样做的优点是它使用告诉,而不是询问,但有一个主要缺点,即代码变得非常难以阅读。
现在我觉得这个演员需要一些好的改变,但我认为有两种选择。
第一个涉及将每个 HttpRequest 和 Response 拆分为单独的 Actor,并将结果聚合到 Connector Actor 中。这样做的优点是可读性强,使用tell并且不会损害性能,因为Akka是为处理大量Actor而构建的。唯一的缺点是我需要为需要从 Stage5Actor 传递到 Connector actor 的这些状态部分创建大量容器类。这会产生很大的内存开销(如果我错了,请纠正我)。
第二种方法是使用“询问”模式将步骤连接在一起。这将导致单个连接器参与者,并且由于 Spray 对其 Http 客户端也这样做,我认为这可能是一个有效的解决方案。唯一的缺点是,因为一切都依赖于外部 Http API,所以超时可能会成为一个问题。如果 Akka 团队推荐这种方法,那么如何处理所有完全不可预测的超时呢?
请注意,此实现需要能够使用监督策略,因为我们当前的整个方法都基于此。
如果您觉得有比我提到的更好的解决方案,请告诉我们!我真的很喜欢 Akka a.t.m.我得到的每一条建议都是经验和知识的增长,不仅对我而且对整个社区:D。另外,我认为这是更多人偶尔遇到的问题。
预先感谢并非常感谢 Akka 团队制作了如此出色的库!
附言。这个问题首先是在 Akka GitHub 上提出的,但我决定将其发布在这里,因为这既是与 Actor 模型相关的问题,也是与 Akka 相关的问题。
GitHub 上问题的链接:https://github.com/akka/akka/issues/16080 https://github.com/akka/akka/issues/16080