我正在Play Framework中构建一个必须进行强烈文件解析的应用程序。这种解析涉及解析多个文件,最好是并行解析。
用户上载已解压缩的存档,并且文件存储在驱动器上。
在该存档中有一个文件(让我们称之为main.csv
),它有多个列。其中一个列是归档中另一个文件的名称(如subPage1.csv
)。此列可以为空,因此并非main.csv
中的所有行都有子页。
现在,我启动一个Akka Actor来解析main.csv文件。在这个演员中,使用@Inject
,我有另一个ActorRef
public MainParser extends ActorRef {
@Inject
@Named("subPageParser")
private AcgtorRef subPageParser;
public Receive createReceive() {
...
if (column[3] != null) {
subPageParser.tell(column[3], getSelf());
}
}
}
SubPageParser道具:
public static Props getProps(JPAApi jpaApi) {
return new RoundRobinPool(3).props(Props.create((Class<?>) SubPageParser.class, jpaApi));
}
现在,我的问题是这个。考虑到子页面可能需要5秒钟才能被解析,我将使用SubPageParser
的单个实例,还是会有多个并行执行处理的实例。
另外,考虑另一个场景,名称存储在DB中,我使用类似的东西:
List<String> names = dao.getNames();
for(String name:names) {
subPageParser.tell(name, null);
}
在这种情况下,考虑到像以前一样使用Guice @Inject获取subPageParser
ActorRef,我会进行并行处理吗?
如果我正在并行处理,我该如何控制正在生成的Actors数量?如果我有1000个子页面,我不想要1000个参与者。此外,他们的生命可能是一个问题。
注意: 我有一个像这样的ActorsModule,所以我可以使用@Inject而不是Props:
public class ActorsModule extends AbstractModule implements AkkaGuiceSupport {
@Override
protected void configure() {
bindActor(MainParser.class, "mainparser");
Function<Props, Props> props = p->SubPageParser.getProps();
bindActor(SubPageParser.class, "subPageParser", props);
}
}
更新:我已修改为使用RoundRobinPool。但是,这不能按预期工作。我将3指定为实例数,但是我为每个解析请求获得了一个新对象。
答案 0 :(得分:2)
像你一样注射演员将导致每SubPageParser
一个MainParser
。虽然您可以向其发送1000条消息(使用tell
),但它们将逐一处理,而其他人则在邮箱中等待处理。
关于你的设计,你需要知道注入这样的actor将创建另一个顶级actor而不是创建SubPageParser
作为子actor,这将允许父actor控制和监控它。 playframework支持注入子actor,如文档中所述:https://www.playframework.com/documentation/2.6.x/JavaAkka#Dependency-injecting-child-actors
虽然你可以让akka使用一定数量的儿童演员分配负载,但我认为你应该质疑为什么你首先使用了演员。大多数问题可以通过简单的Future
来解决。例如,您可以配置自定义线程池以运行Future
,并让他们按照您的意愿在并行化级别执行工作:https://www.playframework.com/documentation/2.6.x/ThreadPools#Using-other-thread-pools