将 Akka 与现有 java 项目集成的示例

Posted

技术标签:

【中文标题】将 Akka 与现有 java 项目集成的示例【英文标题】:Example of integration Akka with existing java project 【发布时间】:2013-05-11 20:00:01 【问题描述】:

如果我已有使用 springservlet 容器的现有 java Web 应用程序。将 Akka 集成到其中的正确方法是什么?

就像我要让Actor1Actor2 相互通信一样。开始使用这些演员的切入点是什么? (比如:1. 把它放在那里 2. 改变配置 3. 获取对actor的引用)

我找到了http://doc.akka.io/docs/akka/2.2-M3/general/configuration.html 但他没有给我胶水。只是想获得集成的真实示例。

有一些简单的集成示例吗?

编辑: 应用程序进行一些搜索,从外部获取一些数据,将信息存储到文件中。

应用程序很大。一些组件/对象可以离开自己的生命,即出于客户端的直接请求,它可以做一些并行的事情。就像一些具有可变状态的单例对象一样。

问题是我不知道我可以在哪里申请演员,我正在调查它。但是我已经在这里和那里有很多同步块。

而且,我相信,这已经是演员可能被应用的一种迹象。 (因为我不确定,可能我忘了放一些同步的,当然也没有集成测试)

关于配置,我只是不确定我是否应该配置一些 application.conf 以让 Actrors/Akka 住在那里(因为文档本身描述了它)。

我看到了什么:

@Component("someManager")
public class SomeManager 
 List<Some> something;  // mutable state, that why I use locks here.
 // methods: add(), delete(), update()  

我可以做到SomeManagerActor

SomeManager 使用自 controller。因此,拥有控制器 Actor 会很好吗?我想收到反馈到(onReceive() 方法)。

这有点争议...这也是我需要一些示例的原因。

我相信我可以通过摆脱所有synchronized/whait/notify 的东西,将责任转移给参与者,使用消息作为他们之间/之间的沟通方式来改进应用程序。

或者像this,它可能是写入属性文件的参与者

编辑:

例如,现在我发现:为了让 Actor1 向 Actor2 发送消息,我使用了一个技巧:

// somewhere in existing code
public void initActors() 

        ActorSystem system = ActorSystem.create(example");

        // initializing
        final ActorRef actor1 = system.actorOf(Props.create(Actor1.class), "actor1");


Actor1 有一个方法preStart(),只要我得到它的引用就会启动它(上图)。并向 Actor2 发送消息:

@Override
public void preStart() 

但我不确定为什么要初始化两个演员来做他们的 工作。

【问题讨论】:

如果您说出您的应用程序是什么以及为什么需要 akka,这将有所帮助。我不明白为什么 Web 应用程序需要 akka,因为您已经拥有消息和异步方法 (Java EE6)。 【参考方案1】:

回答我的问题。只是为了分享我的想法,我想出了什么。

如果我们已经有基于 Servlets/Spring MVC 的现有工作 Web 应用程序,似乎通常没有充分的理由切换到 Actors/AKKA(或将参与者引入现有系统只是为了破解它)如果在我们的应用程序中:

没有: 线程工作者 任务在后台拆分时的逻辑。 (通常,典型的 web 应用程序没有这个),比如 long long 计算。 (并行性)。 有:如果我们有顺序调用 - 当一个组件调用另一个组件时,那么 调用另一个,其中调用相互依赖:像 控制器调用组件,组件将一些数据保存到一些列表中 (它是可变的,但同步为 Synchronized-list )。 没有空闲时间用 Akka Actor 替换所有 Spring Controller 或使用不同的服务器(不是 Tomcat)(没有那么多经理/产品负责人允许你这样做)李>

在这个简单的系统中使用 Actors 有什么问题:

通过组件而不是调用通用方法(利用 OPP 的优势,实现接口,有多个实现——但 Actors 通常是final class)。

将消息作为 string,也不是一个好的解决方案 - 因为它很难调试。

在这样的系统中(比如 MVC 站点),通常没有那么多东西需要同步(已经相当stateless)。每个控制器/组件中有 0..2 个mutable shared data。同步并不难(只需养成将所有常见和共享的同步放在类顶部的习惯(以便状态可识别/本地化)。有时您只需要 synchronized collection 或使用 java Atomic 包装器输入。

当 Actor 可能用于现有应用程序时。用例可能是这样的:

当我们进行长期搜索时,它会经过多个来源(一种线程工作者)。有几个/拉MasterActor -> SiteSearchActor(就像它被描述为计算PI here)。 MasterActor 有最终结果。 SiteSearchActor 为多个客户计算(在多个网站上进行搜索)的位置。 或者当我们有任何线程分叉时,在当前的 servlet 之外 当我们确定/发现我们的系统将被数百万客户使用时(即使是简单的逻辑),我们应该提前考虑scalabilityperformance( 演员规模大 - 我们可以将一项工作从一名演员委托给 N 人。 参与者在处理线程时保护处理器类型(对于 10000 个客户端,不需要 10000 个线程,在大多数情况下足够有 4 个线程(假设与处理器核心数量相同))

但总的来说,我同意this 关于concurrencyparallelism 的文章。如果我有机会从头开始制作应用程序,我会使用 Akka 没有 Servlets 容器 并且 以某种方式关心消息(命令类)和 OOP当需要使用它时(在一般的网络应用程序中没有那么多OOP。无论如何我应该说。但没有人阻止以OOP 的方式保留一些业务逻辑,演员只是一种沟通粘合剂)。例如,这比使用 JMS 更好/更简单。

但就像我说的:

Actor / Akka 适合:

    服务/控制器(而不是 Servlet/SpringMVC 的) 像逻辑一样的线程工作者 特别是对于从头开始的项目(当当前的基础设施不妨碍您应用 actor one 时)。

我现在唯一的问题是performance comparison。假设我们知道:

在一个 JVM 中拥有 10000 个线程,具有同步和共享锁 我们的 MVC 控制器/服务中的可变数据可能非常糟糕 从性能的角度。因为有很多可能的锁, 并发线程(hared 的竞争对手或竞争对手 资源)彼此。

如果我们对具有 N 的 AKKA/Servlet 有相同的场景(参与者,其中 N 比 小于 多于 1000),我们很可能会有更好的性能(因为没有人阻止任何人,除了队列本身,无需从一个线程切换到另一个)。

但是,即使有一个具有 10000 个客户端的基于 Servlet(线程模型)应用程序的系统,具有 100 个客户端它也可能工作得很好。如果我们有一个连接池(当然我们有),它与 Actor 的队列(收件箱)做同样的工作,调度客户端访问某些服务。它可以在 K 次内提高我们的性能(如果我们没有池,K 会更多 - 让线程拼命地相互阻塞)。

问题是:

对于现有的基于 servlet 的应用程序不应用 AKKA 是否有充分的理由?

这是一个论据:即使在服务器上有一个旧系统,与 connection pool 可以将性能提高到一个很好的水平。和这个 水平,很可能,可能足够好,以便不将 AKKA 应用于 现有的 Servlet 应用程序,例如尝试更改 Servlet 模型 (与 AKKA 之上的控制器相比,这应该很糟糕)。

这样想有意义吗?

考虑连接拉取是一种收件箱(就像在 AKKA 中一样)调度 命令(连接)。

即使 Servlets 模型不好(处理由来自连接池的连接创建的剩余(活动)线程中的锁)。

连接池可能已经足够好了,在将 Akka 与基于 servlet 的东西进行比较时,它被遗忘了。我们仍然可以调整我们的应用程序,更改连接池中的 MAX-CONNECTION。通常,我们会尽最大努力使应用程序无状态,因此,在大多数情况下,我们不会同步任何内容。

当然,对于整个应用程序只有一个连接池是不好的。如果与 Actor 相比,每个 Actor 都有自己的连接池(邮箱),并且每个 Actor 可能负责接受 HTTP 请求。那个模型肯定更好。

附: 在大多数情况下,Futures 就足够了。如果您希望“安全”地在其中存储状态,则 Actor 是很好的(这与 Future 基本上不同)。

更新: Some people 相信使用 Actors 是个坏主意。好的是 - 纯函数方法或 scalaz 已经提供的东西(我猜还有 Haskell) - 但还不适用于远程调用。

【讨论】:

【参考方案2】:

我也遇到过类似的问题。

我同意将 AKKA 添加到具有少量用户的简单网络应用程序中几乎没有什么好处。

但我认为将 AKKA 附加到现有的 spring mvc 应用程序并不难。如果您的项目需要扩展,您可以将 @Service 层包装到参与者中。 因此,@Controllers 不需要在演员内部。

这是一个关于将 spring 与 akka 合并的演示文稿: https://www.youtube.com/watch?v=fALUf9BmqYE

演示文稿的源代码: https://github.com/jsuereth/spring-akka-sample/tree/master/src/main/java/org/springframework/samples/travel

【讨论】:

以上是关于将 Akka 与现有 java 项目集成的示例的主要内容,如果未能解决你的问题,请参考以下文章

将 Akka 与 Spring 和 OSGI 集成(未找到密钥“akka”的配置设置)

如何将 vue-cli 添加到现有项目中?

可以将现有的 Java 类与 Actor 集成吗?

大数据技术之_16_Scala学习_11_客户信息管理系统+并发编程模型 Akka+Akka 网络编程-小黄鸡客服案例+Akka 网络编程-Spark Master Worker 进程通讯项目(示例代

Flutter - 将 Flutter 集成到现有项目(iOS - Framework篇)

使用 Amplify 将现有 AWS Cognito 用户池集成到 iOS 项目中