我是 akka 新手。我在本地计算机上的两个节点的两个参与者(Ping Actor 和 Pong Actor)之间制作了一个乒乓球示例,然后以两种不同的方式测试它们。基本上,Ping Actor 会向 Pong Actor 发送一条消息 System.nanoTime()
。收到消息后,Pong Actor 将收到的纳秒时间重新发送回 Ping Actor。
然后我就可以计算出乒乓球一轮所花费的时间。
方式1:main <-> pingActor <-> pongActor
Main1:
for (int i = 0; i < 10; i++) {
pingActor.tell("start", null);
}
PingActor:
public Receive createReceive() {
return receiveBuilder()
.matchEquals("start", start -> {
pongActor.tel(System.nanoTime(), self());
})
.match(String.class, aboveTime -> {
long timeDiff = System.nanoTime() - Long.parseLong(aboveTime);
System.out.println(timeDiff);
})
.build();
}
方式2:main -> pingActor <-> pongActor
Main2:
pingActor.tell("start", null);
PingActor:
public Receive createReceive() {
return receiveBuilder()
.matchEquals("start", start -> {
pongActor.tel(System.nanoTime(), self());
})
.match(String.class, aboveTime -> {
long timeDiff = System.nanoTime() - Long.parseLong(aboveTime);
System.out.println(timeDiff);
pongActor.tel(time, self());
})
.build();
}
我的测试结果表明,第一种方式(平均 100 毫秒)确实比第二种方式(平均 1 毫秒)慢。我需要解释,以及如何从 Actor 外部调用电话与在 Actor 内部调用电话一样快? 谢谢
最佳答案
way1 和 way2 之间的比较不公平。
方式1
Ping
actor会同时处理多条消息,由于Main1
的发送速度太快,一些消息会在邮箱中排队,这导致Pong
的一些响应消息也在Ping
的邮箱中排队,所以这里的差异并不是真正的消息传输速度。
您需要注意,除非您增加nr-of-instances
,否则 Actor 会在一个线程中运行。同时,akka的actor模型不使用协程,在后端它仍然工作在线程池上,所以如果场景更复杂,你可能会发现更多的延迟,所以你需要仔细处理基于akka的应用程序的非阻塞。
方式2
从way1
的解释中,你可以发现你的way2
实际上是以顺序模式运行的,这种差异反射(reflect)了actor之间的真实传输速度,它不包括队列中的缓冲时间。所以它比way1
更快。如果你的Main2
也使用了for循环,速度也会下降;相应地,如果在for循环中添加一些延迟,例如Thread.sleep(1000)
,则way1
的差异会更小。不过,我认为你的 way2
测试数据还是慢了一点,在我的本地机器上,消息传输速度为每秒 50,000+。
如何从 Actor 外部进行调用与在 Actor 内部进行调用一样快?
这确实是一个很大的问题,你所做的只是一种方式,但是你可能需要仔细设计你的actor以充分利用底层线程池,并且你需要了解akka的actor的运行机制,然后你才能让akka在你的应用程序中变得强大。
关于java - 从外部调用 akka actor 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48279768/