Akka设计原则

2024-02-20

在开发一个相当大的 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


在我看来,你不一定需要 N 个阶段来收集回复。如果您知道正在等待多少响应,则可以在单个行为下收集所有响应。

此外,在您使用的任何场景中ask,您可以轻松地将其替换为中间 Actor 来保存此上下文并传递所有消息tell。其实就是这样ask无论如何,但主要区别在于,您不必为每个对象指定超时ask(好吧,您仍然应该为整个请求设置一个超时)并且您可以将所有未完成的阶段捆绑在一个 Actor 中,而不是为每个阶段添加一个额外的 Actorask.

杰米·艾伦(Jamie Allen)对这个场景有很好的描述额外和浮雕图案 http://www.slideshare.net/shinolajla/effective-akka-scalaio in 有效的阿卡 http://shop.oreilly.com/product/0636920028789.do.

因此,考虑到所有这些,您也许可以遵循以下原则:

  • 当Consumer向Connector发送消息时,Connector可以为此请求上下文创建一个新的Actor(Cameo)。你必须捕捉sender该 Actor 中的消费者。
  • 客串演员可以通过以下方式启动后续请求tells。此时,您可以将客串或连接器设置为主管,以便您的监督策略仍然按照您的意愿工作。
  • 其中的客串是Receive块可以等待来自连接的响应。这不一定是await on the ask。只需接受消息中的receive然后更新你的内部状态。
  • 当所有Connection完成后,可以通过以下方式响应原始Consumertell.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Akka设计原则 的相关文章

随机推荐

  • JSoup 不会获取所有项目?

    因此 我尝试使用 JSoup 解析一个简单的列表 不幸的是 程序仅返回列表中以 N 开头的条目之前的条目 我不知道为什么会这样 这是我的代码 public ArrayList
  • 在 Python 中动态参数化多个测试

    我正在尝试使用 Pytest 编写动态测试套件 其中测试数据保存在单独的文件中 例如YAML 文件或 csv 我想运行多个测试 所有这些测试都是从同一个文件进行参数化的 假设我有一个测试文件test foo py 看起来像这样 import
  • 如何在 PRISM 中每次导航时创建新视图?

    我在我的新项目中使用 WPF4 和 PRISM4 有一个模块 其中有多个视图 DI 是统一完成的 当我第一次从 ViewA 导航到 ViewB 时 将创建 ViewB 并调用其构造函数 但是 当我尝试第二次 第三次导航到 ViewB 时 不
  • 如何有效更新两个结构体的值

    我有以下代码 用于解析 YAML 文件并需要匹配一个结构中的值external并更新internal结构体的type财产 例如 这是 yaml 文件 为简单起见 翻译为 bin 和正确解析的内容 package main import fm
  • 如何在Android中使用默认动画?

    我正在尝试使用带有片段的活动的默认动画 在这里我发现了一些关于它的信息 Android 对Fragment使用Activity的默认动画 https stackoverflow com questions 14376810 android
  • Mavericks 上的 MySQL 服务器启动问题

    我在 MacBook 上使用 MySQL 时遇到困难 我正在尝试使用以下命令启动我的服务器sudo mysqld safe这会产生以下输出 140131 00 03 02 mysqld safe Logging to usr local v
  • 不使用 eval/new 函数的 JavaScript 模板库

    Google Chrome 扩展程序使用manifest version 2被限制使用eval or new Function 我检查的所有 JavaScript 模板库 mustachejs underscorejs jQuery 模板
  • Laravel 覆盖命名路线并采取错误的路线

    我在我的routes php 文件中定义了这个 Route post gestionAdministrador array as gt Loguearse uses gt AdministradorController Login Rout
  • 谷歌应用引擎上的 psycopg2 出现问题

    当我尝试在我的谷歌应用程序引擎应用程序中实现框架 Pony ORM 时遇到问题 关键是 Pony 使用 psycopg2 PostgreSQL 适配器 当我尝试向数据库发出请求时 它会引发一个异常 它找不到 psycopg2 模块 在本地
  • data-sly-use、data-sly-resource、data-sly-include 和 data-sly-template 之间有什么区别?

    有什么区别 data sly use data sly resource data sly include and data sly template 我正在阅读文档Sightly AEM我非常困惑 据我所知 data sly use用于添
  • 为 STL 随机数生成器编写工厂方法

    我正在尝试通过配置文件提供一个界面 以便我的用户为他们正在使用的某些参数选择一个发行版 我想使用 STL 随机数生成器算法来实现此目的 假设我的程序从命令行读取 JSON 对于下面提供的 JSON 程序需要意识到它应该根据给定均值和标准差的
  • C# 是否有一个好的 leveldb 端口? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我希望在我的纯 C 项目中使用 leveldb 我在 google 上搜索了 leveldb 的 C 版本 但没有找到 谁能告诉我在哪里可
  • JAXB 按原样使用 String

    我使用 REST 我想知道是否可以告诉 jaxb 将字符串字段 按原样 插入到传出的 xml 中 当然 我想在返回之前将其拆开 但我想节省这一步 XmlRootElement name unnestedResponse public cla
  • 在 Three.js 继承模式中对原型使用扩展有什么好处?

    使用优秀的 Three js 框架 目前正在寻找良好的 javascript 继承模式 我了解了 Three js 中所做的事情 我现在对正在发生的事情有了很好的了解 除了一些 类 例如 Vector3 特别是 我不清楚为什么有些方法是直接
  • 如何在 svelte 中访问 websocket?

    我正在尝试将 svelte 连接到 fastapi 后端 但使用 svelte 套件时出现此错误 我明白了 WebSocket is not defined ReferenceError WebSocket is not defined e
  • cherrypy.HTTPRedirect 使用绝对路径重定向到 IP 而不是主机名

    我在 nginx 后面运行 CherryPy 并需要处理重定向 在我的在 127 0 0 1 8080 上运行的开发机器上 这会正确重定向到 127 0 0 1 8080 login 然而 当通过 nginx 在cherrypy mydom
  • 将数据块读入matlab数组

    我有一个如下所示的数据文件 3 1 0 1 4 1 7 2 1 2 1 5 1 1 1 2 1 1 1 2 对于每一行 第一个整数表示该行中浮点数的数量 现在我想将所有数据加载到一个matlab数组中 并忽略第一列 也就是说 我想得到一个像
  • 原则:多个(whereIn OR whereIn)查询?

    我在用 Doctrine 编写一个相当简单的查询时遇到了麻烦 我有两个数组 countries cities 我需要检查数据库记录值是否与其中的任何一个匹配 我正在寻找类似的东西 gt whereIn country city countr
  • 当文件在其他进程中使用时删除该文件

    In DocumentViewerControl在 WPF 中 我想在关闭事件处理程序中关闭控件后删除该文件 我试图删除它 但 VS 告诉我它被另一个进程使用 我怎样才能删除它 TextBlock tb TextBlock e TabIte
  • Akka设计原则

    在开发一个相当大的 Akka 应用程序时 我在使用普通方法和非 Akka 类时遇到了一个非常简单的结构 但在使用 Akka 时实际上很难确定 这就是为什么我来这里问你什么建议是解决此问题的最佳方法 所以问题是这样的 我有一个父角色 我们称他