При каких обстоятельствах ChannelPipeline удалит все свои элементы? - PullRequest
0 голосов
/ 11 октября 2019

Я тестирую приложение Netty под нагрузкой.

Приложение интенсивно использует отправку задач на EventExecutor , доступную из ChannelHandlerContext#executor(), после рекомендации Нормана Мауэра . (Задачи, которые я отправляю таким образом, сохраняют ссылку на ChannelHandlerContext, действующий на момент отправки.)

Наблюдая за странным поведением в приложении, я зарегистрировал вывод ChannelHandlerContext.pipeline().toMap() из одного изэти задачи в том виде, в каком они выполняются EventExecutor в (определенно) цикле событий.

Зарегистрированный конвейер, на удивление (для меня), пуст.

(Я зарегистрировал конвейер из более обычного channelRead метода, и нет необходимости говорить, что он не пустой.)

В моем приложении нет логики, которая удаляет элементы из ChannelPipeline.

Я не закрываю никакие каналы (клиент запрашивает, чтобы соединения оставались в живых).

Я совершенно уверен, что, должно быть, я что-то не так делаю - возможно, я не уверенкогда ChannelPipeline выходит из области видимости или иным образом "очищается". Когда Netty очищает ChannelPipeline?

1 Ответ

1 голос
/ 14 октября 2019

Netty сама не удаляет обработчики из конвейера. ChannelPipeline собирается GC как обычный объект Java, когда он больше не используется (канал, удерживающий ChannelPipeline закрыт).

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

  • Вы создаете нагрузку на свой сервер;
  • Тестовый клиент не может выдержать достаточную нагрузку и закрывает некоторые соединения (довольно частоситуация во время тестов с высокой нагрузкой);
  • Нетти видит, что соединение закрыто и удаляет канал (и конвейер с ним), и оно собирается с помощью GC;
  • В результате у вас все еще есть контекстто есть ссылки на удаленный канал;

Под нагрузкой этот ChannelHandlerContext «удаляется», и, следовательно, отправленная задача записи не может выполняться при запуске цикла событий.

Это ожидается. Канал может стать недоступным в любой момент. Поэтому, если вы делегируете задачу какому-либо пулу потоков, вы должны проверить, что канал все еще активен / доступен для записи, или вы можете использовать для этого ChannelFuture из операции write().

Обновление:

У вас есть несколько вариантов в зависимости от того, что вам нужно. Вы можете проверить, доступен ли канал для записи перед фактической записью:

if (ctx.channel().isWritable()) {
    //write
}

Вы можете проверить ChannelFuture для результата операции записи:

ChannelFuture cf = ctx.writeAndFlush();
//cf has a bunch of method + listeners that you can use

Вы можете использовать ChannelPromise какну и переопределите требуемый метод.

Нетти очень гибок и обеспечивает множество возможных потоков.

...