以下内容没有回答最初的问题,即当请求进入网络应用程序时,通常需要减少需要创建的新参与者的数量。
要使用 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 文件中定义路由器的类型和行为。
如果您还没有考虑过,那么看看如何使您的网络重新请求异步也是值得的。一种方法是使用 Spring 的 DeferredResult 并将其实例传递给您的参与者,并在搜索请求完成时设置结果。
--2011 年更新--
我认为为什么演员选择对你不起作用是因为你试图使用 bean 名称,而不是演员名称作为演员选择的 pacth。创建路由器时,您没有指定演员名称,因此 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");
}
}
然后您可以通过编写如下代码将其注入另一个 Spring bean:
@Autowired
@Qualifier("routerActorRef")
private ActorRef routerActorRef;
需要注意的是,这只有在顶级actors中才真正可行,对于低级actors也可以,但要有效管理会变得相当棘手。
-- 原始答案--
您链接到的 Main 方法中的示例显示了如何创建一个初始顶级 Actor,该 Actor 将由基于系统的“用户”Actor 监督。这是一个非常简单的示例,演示了创建一个名为 CountingActor 的 Spring 托管 Actor,并在其中注入了一个名为 CountingService 的 Spring 托管 bean。
为了进一步了解这个示例,您可以定义另一个类似于 CountingActor 的演员,例如
@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 时注入。
然后在 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创建和一个主要的区别是使用getContext().actorOf(...)而不是system.actorOf(...)。使用 getContext() 会导致将新 Actor 创建为 CounterActor 的子代,而不是顶级“用户” Actor。
Akka 官方文档中对此行为有很好的描述:http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html#creating-actors-with-props