Завершение работы канала netty TcpClient в Reactor 3.0.4

Я только что обновил projectreactor.io с реактора OLD: [core: 3.0.1 .RELEASE, netty: 0.5.2 .RELEASE] до response. НОВИНКА [core: 3.0.4 .RELEASE, netty: 0.6.0 .RELEASE].

Я открываю соединение TcpClient и хочу закрыть его позже.

В СТАРОЙ версии, которую я использовал

tcpClient.shutdown();

отключить моего клиента от сервера.

Есть ли в НОВОЙ версии аналогичный вызов? Мне не удалось его найти!

Я пробовал следующее на NettyInbound и NettyOutbound, которые я получаю при создании своего TcpClient с tcpClient.newHandler(...)

  • .context().dispose()
  • .context().channel().disconnect()
  • .context().channel().close()
  • TcpResources.reset()

Похоже, что ни один из них не выполняет свою работу правильно.

Я заметил, что вызывается соответствующий .context().onClose(...)-callback. Но после некоторого дополнительного ожидания серверная сторона проверяет соединения. Серверная сторона - это простой NIO2, а не response / netty, и пока клиент был обновлен, серверная сторона осталась неизменной.

Используя СТАРЫЙ клиент, я получил .isOpen() == false для каждого канала на стороне сервера.

С клиентом NEW я получаю .isOpen() == true для каждого канала на стороне сервера. Большую часть времени я даже могу писать на канал. А некоторые каналы переключаются на .isOpen() == false после записи нескольких байтов.


person groovedigga    schedule 06.02.2017    source источник


Ответы (4)


Я думаю, это заслуживает проблемы, особенно если channel (). Close () и reset () не работали. В противном случае это может быть связано с пулом по умолчанию, и TcpClient.create(opts -> opts.disablePool()) может помочь, дайте нам знать, и если у вас есть возможность опубликовать проблему на http://github.com/reactor/reactor-netty ты бы стал героем: D

person smaldini    schedule 07.02.2017
comment
Также включите ведение журнала (через Slf4j) информации, затем выполните отладку для response.ipc.netty. Он должен показывать очень подробную информацию о событиях после каждого вашего звонка. - person smaldini; 07.02.2017
comment
opts.disablePool () не помог. Я постараюсь собрать минимальный пример для воспроизведения и выложить его на github. - person groovedigga; 07.02.2017

Связано с этой открытой проблемой https://github.com/reactor/reactor-netty/issues/15. Мы рассмотрим API удаления.

person smaldini    schedule 13.02.2017
comment
После долгих выходных я нашел время, чтобы собрать тестовый код и поместить его вместе с проблемой на github.com/reactor/reactor-netty/issues/41 - person groovedigga; 14.02.2017

Следующий код каким-то образом уничтожает канал, но не полностью.

ChannelFuture f = nettyContext.channel().close();
f.sync();

nettyContext.dispose();

Проблема в том, что канал все еще кажется открытым на стороне сервера. Для сервера на основе NIO2 сервер не должен проверять, открыт ли канал (). Это всегда правда.

В качестве грязного обходного пути сервер должен писать в канал дважды. Если он перехватывает исключение ExecutionException при второй записи, значит, канал уже закрыт Netty-TcpClient.

try {
    channel.write(ByteBuffer.wrap("hello".getBytes())).get();
    // No exception on first write but on second write.
    channel.write(ByteBuffer.wrap("bye".getBytes())).get();
} catch (ExecutionException e) {
    LOG.log(Level.SEVERE, "ExecutionException on writing from server into channel", e);
}
person groovedigga    schedule 13.02.2017

С реактором-ядром: 3.1.0.M3 и реактором-netty: 0.7.0.M1 клиентский API был улучшен и работает более надежно.
После blockingNettyContext.shutdown() мне все еще нужен следующий обходной путь на стороне сервера, чтобы убедиться, что канал был закрыт:
Мне нужно написать в канал и закрыть его в случае исключения:

// channel.isOpen == true
try {
    channel.write(ByteBuffer.wrap("__test__".getBytes())).get();
} catch (ExecutionException e) {
    channel.close();
}
// channel.isOpen == false
person groovedigga    schedule 17.08.2017