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

18
如果我已经有现有的使用spring和servlet容器的Java Web应用程序,那么集成Akka的正确方式是什么?
比如我将拥有Actor1和Actor2互相通信。什么是启动使用这些actor的入口点?(例如:1.将其放在那里2.更改配置3.获取对演员的引用)
我找到了http://doc.akka.io/docs/akka/2.2-M3/general/configuration.html但它没有为我提供粘合剂。只想得到集成的真实示例。
是否有一些简单的集成示例?
编辑: 应用程序执行一些搜索,从外部获取一些数据,将信息存储到文件中。
该应用程序非常大。一些组件/对象可以离开自己的生活,超出了直接客户端请求的范围,它可以并行执行某些操作。就像一些具有可变状态的单例对象。
事实上,我不确定在哪里可以应用Actor,所以正在调研。但我已经有了很多地方使用了同步块。另外,我相信这可能是使用Actor的信号(因为我不确定,可能忘了加一些同步块,并且当然也没有集成测试)。
至于配置,我不确定是否需要配置一些application.conf文件以让Actors/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东西,把责任转移到actors上,使用消息作为与它们之间通信的方式,我可以改进应用程序。

或者像this这样,它可以成为写入属性文件的actor

编辑:

例如,目前我找到的方法:要使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() {

但我不确定这是初始化两个actor执行任务的好方法。

1
如果您能说明您的应用程序是什么以及为什么需要使用akka,那将会很有帮助。我不明白为什么您需要在Web应用程序中使用akka,因为您已经拥有消息和异步方法(Java EE6)。 - toto2
2个回答

30
回答我的问题。分享一下我的想法,我想到了什么。
如果我们已经有基于Servlets/Spring MVC的现有工作Web应用程序,则似乎没有充分的理由切换到 Actors/AKKA(或者只是为了引入actors而对现有系统进行修改),如果在我们的应用程序中:
- 没有线程工作者逻辑,任务在后台分裂时(通常,典型的Web应用程序没有这个功能),如长时间计算等(并行性)。 - 如果我们有顺序调用- 当一个组件调用另一个组件时,然后该调用另一个组件,其中调用彼此依赖:像控制器调用组件,组件将一些数据保存到某个列表中(它是可变的,但作为Synchronized-list同步)。 - 没有空闲时间来使用Akka actors替换所有Spring Controllers,或完全使用不同的服务器(而不是Tomcat)(没有那么多的经理/产品所有者会允许您这样做)。
在这个简单的系统中使用Actors有什么问题:
- 通过组件传递的大量消息(封装命令到/从actors的类)而不是调用通用方法(利用面向对象编程的优势,实现接口,有几种实现方式 - 但是演员通常是final类)。 - 将消息作为字符串,这也不是一个好的解决方案-因为很难调试。 - 在这样的系统中(如MVC站点),通常没有太多需要同步的事情(它已经相当无状态)。每个控制器/组件有0..2个可变共享数据。这并不难同步(只需养成在类的顶部将所有常见和共享的内容同步的习惯(以便状态可以被识别/定位)。有时您只需要同步集合或使用Java Atomic包装类型。
当演员对现有应用程序可能有用时。用例可能是这样的:
  • 当我们有长期的搜索,需要通过多个来源进行(类似于线程工作者)。拥有多个/拉取 MasterActor -> SiteSearchActor (就像在这里为计算PI所描述的那样)。MasterActor 拥有最终结果。 SiteSearchActor 为多个客户端计算(在多个站点上进行搜索)。
  • 或者当我们有任何线程分支时,超出当前的servlet线程
  • 当我们确定/预测我们的系统将被数百万客户使用(即使是简单逻辑),我们应该提前考虑可扩展性性能
    • actors 很好地扩展-我们可以将一个 actor 的工作委派给 N 个 actor。
    • 处理线程时 actors 安全(不需要为 10000 个客户端使用 10000 个线程,在大多数情况下只需要有 4 个线程(与处理器内核数量相同))

总的来说,我同意这篇关于并发并行的文章。如果我有机会从头开始制作一个应用程序,我将在没有 Servlet 容器的情况下使用 Akka,并在需要使用时(命令类)以及 OOP 方式进行关注(通常Web应用程序中没有太多的OOP。无论如何,没有人阻止将一些业务逻辑保持在OOP方式中,actor 只是一种通信粘合剂)。这比例如使用 JMS 简单得多。

但像我说的那样:

Actor / Akka 适用于:

  1. 服务/控制器(而不是 Servlet/SpringMVC)
  2. 线程工作者模式
  3. 特别是对于从头开始的项目(当当前基础设施不会给您应用 actor 时)。

我现在唯一的问题是性能比较。假设我们知道:

在我们的 MVC 控制器/服务中具有带同步锁的 10000 个线程以及共享可变数据的锁非常糟糕,从性能角度来看。因为有许多可能的锁定,线程之间彼此并发(共享资源的对手或竞争对手)。

如果使用AKKA/Servlets的情况下,有N个actors(其中N远小于1000),那么我们很可能会获得更好的性能(因为没有人阻塞任何人,除了队列本身,不需要从一个线程切换到另一个线程)。
但是即使对于基于Servlets(线程模型)的应用程序拥有10000个客户端的系统,对于100个客户端,它可能运行得非常好。如果我们有一个连接池(当然我们有),它可以执行与Actor的队列(收件箱)相同的工作,调度客户端以访问某些服务。它可以将我们的性能提高K倍(其中K比我们没有连接池要大-让线程彼此绝望地阻塞)。
问题是:是否有足够的理由不将AKKA应用于现有的基于servlet的应用程序?
将其视为论据:即使在服务器上具有旧系统,并且使用连接池可以将性能提高到良好的水平。这个水平很可能足够好,以至于不需要将AKKA应用于现有的Servlet应用程序,就像尝试更改Servlet模型一样(这与在AKKA之上构建控制器相比较应该是不好的)。
这种想法是否有意义?
考虑连接池是一种收件箱(就像在AKKA中一样),调度命令(连接)。
即使Servlets模型不好(在剩余的(活动的)线程中处理来自连接池的连接时涉及锁定),也可能足够好了。
与Akka相比,这个连接池被忽略了。我们仍然可以调整应用程序,更改连接池中的MAX-CONNECTION。通常,我们会尽最大努力使应用程序无状态,因此,在大多数情况下,我们不需要同步任何内容。
但是,只有一个连接池用于整个应用程序是不好的。与Actors相比,每个Actor都有自己的连接池(邮箱),并且每个Actor可能负责接受HTTP请求。那种模型肯定更好。

P.S. 在大多数情况下,Future已经足够好了。如果你想要在其中“安全”存储状态(这与 Future 有所不同),那么 Actors 是一个好选择。

更新: 有些人认为使用 Actors 根本就是个坏主意。好的方案是 —— 纯函数式方法或者像 scalaz 已经提供的方式一样(我猜 Haskell 也是)——但远程调用还没有准备好。


3

我遇到了类似的问题。

我认为在用户数量较少的简单Web应用程序中添加AKKA没有多少好处。

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

这里是有关将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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接