Tomcat 中有很多 Akka 线程
Lots of Akka Threads in Tomcat
我在 Tomcat 8 中托管我的 Scala (2.11) WAR 并使用 akka
2.3.+ 和 spray-client
1.3.3。我只为一个演员使用 Akka,并在 Tomcat 开始时向它发送一次调用。也可以手动调用。
class RefreshDataActor extends Actor with ActorLogging {
override def receive: Receive = {
case _ =>
implicit val timeout: Timeout = someTimeout
implicit val ec = this.context.dispatcher
val pipeline = sendReceive ~> unmarshal[Data]
pipeline(Get(fileUrl))
.onComplete {
case Success(data) =>
// Do stuff with the data
case Failure(ex) =>
this.log.error("Unable to find the latest version of the data!", ex)
}
}
}
每当有任何调用进入 Tomcat 时,我都会看到它托管的活动线程数量激增。
箭头指示对服务器进行调用的时间。另请注意,CPU 也缓慢上升,并且在某些时候机器最终会在看似什么都没有的情况下非常努力地工作(屏幕截图中的机器有 8 个内核)。
我通过将 VisualVM 连接到其中一台受此影响的计算机来开始调试该问题。保持活动状态的线程被命名为 default-akka.actor.default-dispatcher-X
(其中 X
通常是 2 到 7 之间的任何数字),所有线程都是 WAITING 和 default-scheduler-1
(TIMED_WAITING)。 有数百个。还有一个 default-akka.io.pinned-dispatcher-5
(可运行)。
我假设这与 Akka 的工作方式有关,但不明白这是为什么。
发现问题。我不止一次调用 ActorSystem()
,这创建了一个新的 actor 系统,而不是重用已经创建的系统。这导致越来越多的系统被创建,并且出于某种原因没有被删除。
我在 Tomcat 8 中托管我的 Scala (2.11) WAR 并使用 akka
2.3.+ 和 spray-client
1.3.3。我只为一个演员使用 Akka,并在 Tomcat 开始时向它发送一次调用。也可以手动调用。
class RefreshDataActor extends Actor with ActorLogging {
override def receive: Receive = {
case _ =>
implicit val timeout: Timeout = someTimeout
implicit val ec = this.context.dispatcher
val pipeline = sendReceive ~> unmarshal[Data]
pipeline(Get(fileUrl))
.onComplete {
case Success(data) =>
// Do stuff with the data
case Failure(ex) =>
this.log.error("Unable to find the latest version of the data!", ex)
}
}
}
每当有任何调用进入 Tomcat 时,我都会看到它托管的活动线程数量激增。
箭头指示对服务器进行调用的时间。另请注意,CPU 也缓慢上升,并且在某些时候机器最终会在看似什么都没有的情况下非常努力地工作(屏幕截图中的机器有 8 个内核)。
我通过将 VisualVM 连接到其中一台受此影响的计算机来开始调试该问题。保持活动状态的线程被命名为 default-akka.actor.default-dispatcher-X
(其中 X
通常是 2 到 7 之间的任何数字),所有线程都是 WAITING 和 default-scheduler-1
(TIMED_WAITING)。 有数百个。还有一个 default-akka.io.pinned-dispatcher-5
(可运行)。
我假设这与 Akka 的工作方式有关,但不明白这是为什么。
发现问题。我不止一次调用 ActorSystem()
,这创建了一个新的 actor 系统,而不是重用已经创建的系统。这导致越来越多的系统被创建,并且出于某种原因没有被删除。