Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Akka与Spring集成_Java_Spring_Akka - Fatal编程技术网

Java Akka与Spring集成

Java Akka与Spring集成,java,spring,akka,Java,Spring,Akka,我正在尝试让akka使用spring应用程序。这是一款搜索应用程序,完全符合akka模式。在线和类型安全上关于此集成的大多数示例都谈到使用akka扩展注入spring应用程序上下文。但是,它们都使用ActorSystem.actorOf()方法来创建参与者,这是一个代价高昂的操作 ActorSystem system = ctx.getBean(ActorSystem.class); system.actorOf(.....) 见- 我想使用actors来处理通过身份验证的每个web请求。通过

我正在尝试让akka使用spring应用程序。这是一款搜索应用程序,完全符合akka模式。在线和类型安全上关于此集成的大多数示例都谈到使用akka扩展注入spring应用程序上下文。但是,它们都使用
ActorSystem.actorOf()
方法来创建参与者,这是一个代价高昂的操作

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

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


任何建议都将不胜感激。

下面的内容并没有回答最初的问题,即当请求进入web应用程序时,减少通常需要创建的新参与者的数量

要使用Akka路由器做到这一点,只需以下代码行即可:

getContext().actorOf(SpringExtProvider.get(getContext().system()).props("AnotherActor.").withRouter(new RoundRobinPool(100)), "another");
Akka文档提供了更多关于配置的详细信息,但值得一看。最好通过Akka配置文件来定义他们的行为,而不是硬编码到应用程序中。你可以这样称呼它:

getContext().actorOf(SpringExtProvider.get(getContext().system()).props("AnotherActor.").withRouter(new FromConfig()), "another");
..并在application.conf文件中定义路由器的类型和行为

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

--11月20日更新--

我认为,为什么演员选择对您不起作用,是因为您试图使用bean名称,而不是演员名称作为演员选择的PACT。在创建路由器时,您不指定参与者名称,因此Akka会在内部为其命名,例如“$a”

举例来说,如果您使用以下内容创建演员:

actorSystem.actorOf(this.get(actorSystem).props(applicationContext, "bean_name"), "actorName");
然后,您应该能够使用以下选项执行演员选择:

actorSystem.actorSelection("actorName");
或者,创建一次以上的路由器actor,然后在向Spring MVC web服务发出的每个请求中重复使用它,您可以在Spring@Configuration类中创建它,并将ActorRef作为bean公开,以便可以注入到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");
   }

}
然后,您可以通过编写以下内容将其注入另一个Springbean:

@Autowired
@Qualifier("routerActorRef")
private ActorRef routerActorRef;
应该注意的是,这只有在顶级参与者中才是切实可行的,在较低级别的参与者中也是可能的,但要有效地进行管理将变得相当棘手

--原始答案--

您链接到的主要方法中的示例显示了如何创建初始顶级参与者,该参与者将由基于系统的“用户”参与者进行监督。这是一个非常简单的示例,演示了如何创建名为CountingActor的Spring托管actor,并将名为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()方法,在创建另一个actor时将注入该方法

然后在CountingActor中,您可以创建另一个Actor,如下所示:

@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创建与main之间的关键区别在于使用了getContext().actorOf(…)而不是system.actorOf(…)。使用getContext()会导致将新参与者创建为反作用器的子级,而不是顶级“用户”参与者


Akka官方文档中对此行为有很好的描述:

谢谢,但这并不能回答我的主要担忧——“我想使用参与者来处理通过身份验证的每个web请求。使用上述代码,我将为每个不理想的请求创建根参与者。”此外,下面一行每次都会创建一个参与者-如何在此处添加路由器?ActorRef anotherActor=getContext().actorOf(SpringExtProvider.get(system.props)(“anotherActor”),“另一个”);我已经更新了上面的答案,为误解道歉。我认为你想要达到的目标应该是相当简单的。谢谢。但是,这对根actor不起作用,因为我无法为使用spring上下文->actorSystem.actorOf(this.get(actorSystem.props)(applicationContext,“bean\u name”)创建的actor执行actorSystem.actorSelection(“bean\u name”)。因此,它结束了为每个web请求创建actor及其子对象!要解决这个问题,您可以在Spring@Configuration类中将router actor的ActorRef作为springbean公开。我将在上面的答案中添加一个简短的、未经测试的代码片段,以演示我的意思。检查单元测试的使用情况。但它基本上与使用上面提到的编程spring配置相同。