akka.pattern.after:内存泄漏
akka.pattern.after: Memory Leak
以下代码导致我的 play Scala Web 服务发生内存泄漏。当我使用 threadDump 时,我注意到 PluginTimeout 线程一直在等待并且永远不会被执行。
override final def execute:Future[Any] = {
val f1 = executePlugin // this returns a future
val system = ActorSystem("PluginTimeout")
val timeoutFuture = akka.pattern.after(timeout, system.scheduler) { throw new TimeoutException(s"{$name} timed out") }
Future.firstCompletedOf(f1 :: timeoutFuture :: Nil)
}
这就是我的线程转储的样子。在进行了几次线程转储后,我注意到 PlugintTimeout 对象的数量在每个后续线程转储中不断增加。
"PluginTimeout-akka.actor.default-dispatcher-2" #2308 prio=5 os_prio=31 tid=0x00007fa02c84f800 nid=0x88707 waiting on condition [0x00000001803a3000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007ab6f5d68> (a akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinPool)
at scala.concurrent.forkjoin.ForkJoinPool.scan(ForkJoinPool.java:2075)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Locked ownable synchronizers:
- None
"PluginTimeout-scheduler-1" #2307 prio=5 os_prio=31 tid=0x00007fa02b34f800 nid=0x80f07 sleeping[0x000000017f16d000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at akka.actor.LightArrayRevolverScheduler.waitNanos(LightArrayRevolverScheduler.scala:81)
at akka.actor.LightArrayRevolverScheduler$$anon.nextTick(LightArrayRevolverScheduler.scala:260)
at akka.actor.LightArrayRevolverScheduler$$anon.run(LightArrayRevolverScheduler.scala:230)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
如果我从我的方法中删除 Future 超时逻辑,我不会发现任何内存泄漏问题。这里可能发生了什么。一种可能的解释是,如果另一个未来成功并一直等待永恒,timeoutFuture 永远不会被执行。这会导致多个期货堆积起来并占用内存。有什么线索吗?
您正在创建大量 ActorSystem(n
个系统用于 n
个执行调用)。
ActorSystem 比较重,因为它包含配置 ThreadPools 等。
您应该改用 1
ActorSystem 并在您的逻辑中使用它。
例如通过隐式传递它:def execute()(implicit system: ActorSystem)
以下代码导致我的 play Scala Web 服务发生内存泄漏。当我使用 threadDump 时,我注意到 PluginTimeout 线程一直在等待并且永远不会被执行。
override final def execute:Future[Any] = {
val f1 = executePlugin // this returns a future
val system = ActorSystem("PluginTimeout")
val timeoutFuture = akka.pattern.after(timeout, system.scheduler) { throw new TimeoutException(s"{$name} timed out") }
Future.firstCompletedOf(f1 :: timeoutFuture :: Nil)
}
这就是我的线程转储的样子。在进行了几次线程转储后,我注意到 PlugintTimeout 对象的数量在每个后续线程转储中不断增加。
"PluginTimeout-akka.actor.default-dispatcher-2" #2308 prio=5 os_prio=31 tid=0x00007fa02c84f800 nid=0x88707 waiting on condition [0x00000001803a3000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007ab6f5d68> (a akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinPool)
at scala.concurrent.forkjoin.ForkJoinPool.scan(ForkJoinPool.java:2075)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Locked ownable synchronizers:
- None
"PluginTimeout-scheduler-1" #2307 prio=5 os_prio=31 tid=0x00007fa02b34f800 nid=0x80f07 sleeping[0x000000017f16d000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at akka.actor.LightArrayRevolverScheduler.waitNanos(LightArrayRevolverScheduler.scala:81)
at akka.actor.LightArrayRevolverScheduler$$anon.nextTick(LightArrayRevolverScheduler.scala:260)
at akka.actor.LightArrayRevolverScheduler$$anon.run(LightArrayRevolverScheduler.scala:230)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
如果我从我的方法中删除 Future 超时逻辑,我不会发现任何内存泄漏问题。这里可能发生了什么。一种可能的解释是,如果另一个未来成功并一直等待永恒,timeoutFuture 永远不会被执行。这会导致多个期货堆积起来并占用内存。有什么线索吗?
您正在创建大量 ActorSystem(n
个系统用于 n
个执行调用)。
ActorSystem 比较重,因为它包含配置 ThreadPools 等。
您应该改用 1
ActorSystem 并在您的逻辑中使用它。
例如通过隐式传递它:def execute()(implicit system: ActorSystem)