我是 Akka 框架的新手,我正在用它构建一个群聊应用程序。我的应用程序可能有 1000 万个相同类型的 actor 实例(每个群聊一个 actor 实例),其中只有 5% 是高度活跃的,而其中 60% 可以闲置数天(不接收任何消息)。
我想知道:
是否有任何最佳实践来识别这些闲置演员?
演员ActorContext有一个setReceiveTimeout方法来定义演员的不活动阈值:如果演员在给定的时间内没有收到消息,则akka.actor.ReceiveTimeout向演员发送一条消息。例如:
import akka.actor.{ Actor, ReceiveTimeout }
import scala.concurrent.duration._
class ChatActor extends Actor {
context.setReceiveTimeout(2 hours)
def receive = {
case ReceiveTimeout =>
// do something
// other case clauses
}
}
Run Code Online (Sandbox Code Playgroud)
上面如果两个小时没有收到消息ChatActor就会收到ReceiveTimeout消息。(但是,正如文档所述:“接收超时可能会ReceiveTimeout在另一条消息入队后立即触发并将消息入队;因此,不能保证在接收到接收超时时必须事先有一个空闲时间,如通过此方法配置的.”)
处理它们的最佳做法是什么?
停止不活跃的演员是个好主意;否则你可能会出现内存泄漏。以下是一些阻止这些 actor 的方法:
context stop sender())。self引用发送到“收割者”actor,该actor 收集对空闲actor 的引用并定期剔除(即停止)这些actor(可能使用调度程序)。context stop self)。可以在此处找到有关停止 actor 的更多信息。
阻止他们就够了吗?
当一个actor被停止时,它ActorRef本质上就变得无效了。从文档:
在停止一个actor 之后,它的
postStop钩子被调用,这可以用于例如从其他服务中注销这个actor。此挂钩是保证运行后,消息队列已为此演员禁止,即发送到停止演员的消息将被重定向到deadLetters的ActorSystem。
此时,现在陈旧ActorRef指向的底层 actor 实例有资格进行垃圾回收。换句话说,为了有资格进行垃圾回收,必须停止一个actor。因此,在释放内存方面,停止actor就足够了。您还可以ActorRef在演员停止后删除无效本身。请注意,删除 anActorRef不会自动停止 actor:
需要注意的是,Actor 不再被引用时不会自动停止,每个创建的 Actor 也必须显式销毁。