我是Akka框架的新手,我正在用它构建群聊应用程序。我的应用程序可能有相同类型的1000万个actor实例(每个组聊天的一个actor实例),其中只有5%是高度活跃的,其中60%可以闲置(没有接收任何消息)数天。
我想知道:
答案 0 :(得分:4)
有没有最佳做法来识别这些空闲演员?
演员的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
}
}
如果上述ChatActor
在两小时内未收到消息,则会收到ReceiveTimeout
条消息。 (但是,正如文档所述:“接收超时可能会在另一条消息入队后立即触发ReceiveTimeout
消息;因此无法保证在接收到接收超时后必须是通过此方法预先配置的空闲时段。“)
处理它们的最佳做法是什么?
停止不活跃的演员是一个好主意;否则你可能会有内存泄漏。以下是一些阻止这些演员的方法:
context stop sender()
)。self
引用发送给“收割者”参与者,该参与者定期收集对空闲参与者的引用并剔除(即停止)这些参与者(可能使用scheduler)。 context stop self
)。有关停止演员的更多信息,请here。
是否足够阻止他们?
当演员停止时,其ActorRef
基本上无效。来自documentation:
在停止演员后,调用其
postStop
挂钩,可以使用例如从其他服务取消注册此actor。保证在为此actor禁用消息队列后运行此挂钩,即发送给已停止的actor的消息将重定向到deadLetters
的{{1}}。
此时,现在陈旧ActorSystem
点的基础actor实例有资格进行垃圾回收。换句话说,必须停止一个actor才有资格进行垃圾收集。因此,关于释放内存,停止演员就足够了。您还可以在actor停止后删除无效的ActorRef
。请注意,removing an ActorRef
不会自动停止actor:
值得注意的是,Actors在不再引用时不会自动停止,每个创建的Actor也必须明确销毁。
答案 1 :(得分:0)
唯一的方法是让每个演员保持上次活动的时间。然后,为了加速对最长的非活动actor的调查,你可以组织一个类似索引的结构,例如,的PriorityQueue。然后,一个专门的演员定期唤醒并清除那些闲置时间超过某个预定义时间段的演员的结构。
空闲actor不消耗除核心内存之外的任何资源。如果你有足够的记忆力,最好的做法是什么都不做。如果要保存该内存,请将actor存储在数据库中(经过一段时间不活动),然后按需从那里读取它。