我已经测试一个基于 Akka 的应用程序一个多月了。但是,如果我反射(reflection)一下,我有以下结论:
- 单独使用 Akka actor 可以实现大量并发。我已经达到了超过 100,000 条消息/秒。这很好,只是消息传递。
- 现在,如果一端有用于连接的 netty 层,或者您最终使用 akka actor 进行数据库调用、REST 调用、写入文件,那么整个系统就不再有意义了。 Actor 的邮箱已满,他们的吞吐量(此处为每秒接收消息的能力)变慢。
- 从 QA 的角度来看,这就像有一个巨大的管道,您可以在其中强行泵入大量水并且它可以处理。但是,如果输入软管坏了,或者端点无法承受压力,那么这个巨大的管道就没有用了。
我需要以下问题的答案,以便我可以在系统中建议或验证:
- 像 DB 调用、REST 调用这样的阻塞调用应该由 actor 处理吗?或者它们只适用于消息传递?
- 是否可以这样说,假设您需要将数百万个 android/ios 设备持续连接到您的 akka 系统。除了套接字(如此不可靠)等,远程参与者是否可以实现为持久连接?</li>
- 是否可以在 actor 的
handleMessage()
中进行任何类型的计算?像数据库调用等。
我会要求编辑通过这篇文章。我不能单独询问所有这些。
最佳答案
1) 是的,他们可以。但是这个操作应该在单独的( worker )actor 中完成,它结合使用 fork-join-pool 和 scala.concurrent.blocking
围绕阻塞代码,它需要它来防止线程饥饿。如果目标系统(DB、REST 等)支持多个并发连接,您可以为此使用 akka 的路由器(为池中的每个连接创建一个参与者)。您还可以为多个不同的表(资源、队列等)生成多个参与者,具体取决于您的事务隔离和存储的一致性要求。
处理此问题的另一种方法是使用带有确认而不是阻塞的异步请求。您也可以将阻塞操作放在一些单独的 future (线程、工作线程)中,它将在操作结束时发送确认消息。
2) 是的,actor 可以实现为持久连接。它将只是一个 actor,它保存连接的状态(因为 actor 是有状态的)。使用 Akka Persistence 可能更可靠,这可以节省与某些存储的连接。
3) 您可以在 actor 的 receive
中进行任何非阻塞计算(akka 中没有 handleMessage
方法)。失败(比如没有连接到数据库)将由 Akka Supervising 自动管理。阻塞代码见1。
附言关于“巨大的管道”。后端应用程序本身是一个管道(它随着 akka 变得越来越大),所以如果环境无法处理它,没有什么可以帮助您提高性能 - 这个世界上没有泵。但akka也是一个“水箱”,这意味着外部压力可能比内部压力大。顺便说一句,这意味着开发人员应该小心邮箱 - 因为“水太多”可能会导致内存不足,防止这种情况的方法是组织 back pressure .这可以通过不确认传入消息(或简单地阻止端点的处理程序)直到它由 akka 处理来完成。
关于java - QA 视角下的 Akka 系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29230225/