gpt4 book ai didi

scala - 带有网络套接字的 Akka http 内存泄漏

转载 作者:行者123 更新时间:2023-12-03 17:31:23 27 4
gpt4 key购买 nike

我有一个 Web 服务器,它接受传入的 websocket 连接,在 Scala 中使用 akka http 实现。但是,我一直在观察我的应用程序的内存使用量单调增加。经过长时间的挖掘,我发现每个连接都会创建一些内部 Akka 对象,但在客户端断开连接后不会被清除。特别是这个类(class):akka.stream.impl.fusing.ActorGraphInterpreter .每个连接都会创建一个新的此类对象。我用过 jmap要计算对象的数量,请使用下面提供的命令。我不确定我在这里做错了什么。任何建议将不胜感激。
我有一个 super 简单的 echo websocket 服务器来复制这个观察:

package samples

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.ws.{Message, TextMessage}
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Flow, Source}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.io.StdIn

object AkkaWsExample {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()

private val greeterWebSocketService = {
Flow[Message]
.collect {
case tm: TextMessage =>
println(s"Received $tm")
TextMessage(Source.single("Hello ") ++ tm.textStream)
}
}

def main(args: Array[String]): Unit = {

//#websocket-routing
val route =
path("greeter") {
get {
handleWebSocketMessages(greeterWebSocketService)
}
}

val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)

println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // for the future transformations
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
}
}
然后我使用任何方法连接到该服务器并断开连接,并运行 jmap 来计算对象计数,并注意到每个连接严格 1 个新对象。我也尝试了数千个连接,同样的事情发生了。
我用这个命令来计算对象的数量:

jmap -histo:live [pid] | grep ActorGraphInterpreter


这是启动时和打开和关闭 1000 个连接后的结果

ip-192-168-30-10:~ liuh$ jps | grep Akka | awk '{print $1}' | xargs jmap -histo:live | grep ActorGraphInt | head -n1

701: 1 56 akka.stream.impl.fusing.ActorGraphInterpreter

ip-192-168-30-10:~ liuh$ jps | grep Akka | awk '{print $1}' | xargs jmap -histo:live | grep ActorGraphInt | head -n1

119: 1001 56056 akka.stream.impl.fusing.ActorGraphInterpreter


您可以看到对象计数严格按照连接数增加。我确保我的客户端已断开连接 - 我关闭了进程并通过 netstat 进行了验证连接已关闭。

最佳答案

您可能没有考虑到 Scala 基于 JVM 的事实,该 JVM 使用垃圾收集器,而后者又不是确定性的。特别是如果您没有产生足够的内存压力(与允许的内存限制相比),GC 可能根本不会运行。您可以通过强制 GC 轻松验证该理论(这在生产中很可能很糟糕,但可以调试)。尝试添加到您的 main 的开头方法如下代码:

new Thread() {
override def run(): Unit = {
println("Start GC-thread")
val start = System.currentTimeMillis()
while (true) {
Thread.sleep(1000)
System.gc()
}
}
}.start()

这段代码启动了一个独立的线程,它会要求 VM 每秒执行一次 GC。我敢打赌,使用这样的代码,您的测试将不会显示超过几个活着的 ActorGraphInterpreter对象。至少这是我在你的例子中看到的。如果你还看到很多 ActorGraphInterpreter在您的实际代码中,您的示例可能不够完善 MCVE你应该发布一个更好的。

关于scala - 带有网络套接字的 Akka http 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53490672/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com