Утечка HTTP-памяти в Akka через веб-сокет

У меня есть веб-сервер, который принимает входящее соединение через веб-сервер, реализованный с помощью akka http в Scala. Однако я наблюдал монотонное увеличение использования памяти моим приложением. После долгих поисков я обнаружил, что некоторые внутренние объекты Akka создаются при каждом подключении, но не очищаются после отключения клиента. Специально этот класс: akka.stream.impl.fusing.ActorGraphInterpreter. Для каждого соединения создается один новый такой объект. Я использовал jmap для подсчета количества объектов, команда приведена ниже. Не уверен, что я здесь что-то не так делаю. Любые советы будут высоко ценится.

У меня есть супер простой сервер 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, что соединения были отключены.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
573
1

Ответы 1

Вы, вероятно, не учитываете тот факт, что Scala основана на JVM, которая использует сборщик мусора, который, в свою очередь, не является детерминированным. В частности, если вы не создаете достаточной нагрузки на память (по сравнению с допустимым пределом памяти), сборщик мусора может вообще не работать. Вы можете легко проверить эту теорию, принудительно запустив сборку мусора (что в большинстве случаев, вероятно, плохо в производственной среде, но подходит для отладки). Попробуйте добавить в начало вашего метода main следующий код:

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

Этот код запускает независимый поток, который будет просить виртуальную машину выполнять сборку мусора каждую секунду. Готов поспорить, что с таким кодом ваш тест покажет не более нескольких живых объектов ActorGraphInterpreter. По крайней мере, это то, что я вижу в вашем примере. Если вы все еще видите много ActorGraphInterpreter в своем реальном коде, ваш пример, вероятно, является неадекватным MCVE, и вам следует опубликовать лучший вариант.

Спасибо за предложение. jmap -histo: live фактически вызывает полный сборщик мусора. Я разобрался в проблеме. Это ошибка в akka-http. Версия, которую я использовал, была лишь той, где это было введено, но еще не исправлено. github.com/akka/akka-http/issues/2067

user1861088 28.11.2018 20:34

Привет. Какую версию вы используете? У меня точно такая же проблема

Rabzu 06.12.2018 20:35

@ user1861088, последний вопрос наверное адресован вам

SergGr 06.12.2018 20:39

Другие вопросы по теме