java - Akka 和 Spring 集成

标签 java spring akka

我正在尝试让 akka 使用 spring 应用程序。这是一个完美契合akka模型的搜索应用。大多数关于此集成的在线示例和类型安全示例都在讨论使用 akka 扩展来注入(inject) spring 应用程序上下文。但是,它们都使用 ActorSystem.actorOf() 方法来创建已知操作开销很大的 actor。

ActorSystem system = ctx.getBean(ActorSystem.class);
system.actorOf(.....)

参见 - https://github.com/typesafehub/activator-akka-java-spring/blob/master/src/main/java/sample/Main.java

我想使用 actor 来处理每个通过身份验证的 Web 请求。使用上面的代码,我最终会为每个不理想的请求创建根参与者。

如有任何指点,我们将不胜感激。

最佳答案

下面没有回答原始问题,即当请求进入网络应用程序时,通常需要减少新参与者的数量。

要使用 Akka 路由器做到这一点,它可以像以下代码行一样简单:

getContext().actorOf(SpringExtProvider.get(getContext().system()).props("AnotherActor.").withRouter(new RoundRobinPool(100)), "another");

Akka 文档提供了更多关于配置的详细信息,尽管值得一看 http://doc.akka.io/docs/akka/snapshot/java/routing.html .最好通过 Akka 配置文件定义它们的行为,而不是硬编码到应用程序中。你可以这样调用它:

getContext().actorOf(SpringExtProvider.get(getContext().system()).props("AnotherActor.").withRouter(new FromConfig()), "another");

..并在您的 application.conf 文件中定义路由器的类型和行为。

如果您还没有考虑过,也值得了解一下如何使您的 Web 重新请求异步化。一种方法是使用 Spring 的 DeferredResult 并将其实例传递给您的参与者,并在搜索请求完成时设置结果。

--2011 年 11 月更新--

我认为为什么 Actor 选择对您不起作用是因为您试图使用 bean 名称,而不是 Actor 名称作为 Actor 选择的路径。创建路由器时,您没有指定 Actor 名称,因此 Akka 会在内部为其指定一个名称,例如“$a”。

举例来说,如果您使用以下方法创建 actor:

actorSystem.actorOf(this.get(actorSystem).props(applicationContext, "bean_name"), "actorName");

然后您应该能够执行 Actor 选择:

actorSystem.actorSelection("actorName");

或者创建一次上述路由器 actor,然后在对 Spring MVC web 服务发出的每个请求中重新使用它,您可以在 Spring @Configuration 类中创建它并将它的 ActorRef 公开为一个 bean,这样您可以注入(inject)你的 Spring @Controller 类。以下是我创建的 frmo 内存的一个简单示例,因此请确保它经过测试/编译等。

@Configuration
public class Config {

   @Autowired
   private ActorSystem actorSystem;

   @Bean(name = "routerActorRef")
   public ActorRef routerActorRef() { 
      getContext().actorOf(SpringExtProvider.get(actorSystem).props("AnotherActor").withRouter(new RoundRobinPool(100)), "another");
   }

}

然后您可以通过编写如下内容将其注入(inject)到另一个 Spring bean 中:

@Autowired
@Qualifier("routerActorRef")
private ActorRef routerActorRef;

应该注意的是,这只对顶级 actor 才真正可行,对较低级别的 actor 也是可行的,但要有效管理会变得非常棘手。

-- 原答案--

您链接到的 Main 方法中的示例显示了如何创建初始顶级参与者,该参与者将由基于系统的“用户”参与者监督。这是一个非常简单的示例,演示如何创建一个名为 CountingActor 的 Spring 托管 actor,并向其中注入(inject)一个名为 CountingService 的 Spring 托管 bean。

为了更深入地了解这个例子,您可以定义另一个看起来类似于 CountingActor 的 actor,例如

@Named("AnotherActor")
@Scope("prototype")
class AnotherActor extends UntypedActor {

  // the service that will be automatically injected
  final AnotherService anotherService;

  @Inject
  public AnotherActor(@Named("AnotherService") AnotherService anotherService) {
    this.anotherService = anotherService;
  }    

  @Override
  public void onReceive(Object message) throws Exception {
    if (message == "doSomething") {
      anotherService.doSomething();
    } else {
      unhandled(message);
    }
  }
}

我假设有另一个名为 AnotherService 的 Spring 服务 bean,它有一个 doSomething() 方法,该方法将在创建 AnotherActor 时注入(inject)。

然后在 CountingActor 中,您可以像这样创建 AnotherActor:

@Named("CountingActor")
@Scope("prototype")
class CountingActor extends UntypedActor {

  public static class Count {}
  public static class Get {}

  // the service that will be automatically injected
  final CountingService countingService;

  @Inject
  public CountingActor(@Named("CountingService") CountingService countingService) {
    this.countingService = countingService;
  }

  private int count = 0;

  @Override
  public void onReceive(Object message) throws Exception {
    if (message instanceof Count) {
      count = countingService.increment(count);
      // Create AnotherActor here as a child of CountingActor by using the CountingActor's context
      ActorRef anotherActor = getContext().actorOf(SpringExtProvider.get(system).props("AnotherActor"), "another");
      anotherActor.tell("doSomething", getSelf());
    } else if (message instanceof Get) {
      getSender().tell(count, getSelf());
    } else {
      unhandled(message);
    }
  }
}

此处创建的 actor 与之前创建的 actor 之间的主要区别在于使用 getContext().actorOf(...) 而不是 system.actorOf(...)。使用 getContext() 会导致新角色被创建为 CounterActor 的子角色,而不是顶级“用户”角色。

官方 Akka 文档中对此行为有很好的描述:http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html#creating-actors-with-props

关于java - Akka 和 Spring 集成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26920120/

相关文章:

java - 属性文件似乎产生空指针异常?

java - TCP 套接字上的 ObjectOutputStream

scala - 我如何模拟 future 的 onComplete 方法?

c# - 传递上下文信息

java - 使用 Appengine 进行多线程

java - 如何从 JSON 输出字符串中提取各个数据片段?

spring - 另一个未命名的 CacheManager 已存在于同一虚拟机中(ehCache 2.5)

java - 在网络应用程序中发送文件后如何删除文件?

java - spring security 不符合自动代理的条件

akka - future pipeTo 失败被包裹在 akka.actor.status.Failure 中?