【问题标题】:Shutting down a netty TcpClient channel in Reactor 3.0.4关闭 Reactor 3.0.4 中的 netty TcpClient 通道
【发布时间】:2017-06-23 11:51:50
【问题描述】:

我刚刚从 reactor OLD 升级了 projectreactor.io:[core: 3.0.1.RELEASE, netty: 0.5.2.RELEASE ] 到反应堆 NEW [core: 3.0.4.RELEASE, netty: 0.6.0.RELEASE].

我打开一个 TcpClient 连接并想稍后关闭它。

在我使用的OLD版本中

tcpClient.shutdown();

断开我的客户端与服务器的连接。

新版本中是否有等效的调用?我找不到!

我在使用 tcpClient.newHandler(...) 创建 TcpClient 时得到的 NettyInboundNettyOutbound 上都尝试了以下操作

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

他们似乎都没有正确地完成这项工作。

我注意到正在调用相应的.context().onClose(...)-callback。 但是经过一些额外的等待,服务器端会检查连接。 服务器端是普通的 NIO2 而不是 reactor/netty,当客户端升级时,服务器端保持不变。

使用 OLD 客户端,我在服务器端的每个频道都获得了.isOpen() == false

使用 NEW 客户端,我会为服务器端的每个频道获得 .isOpen() == true。大多数时候我什至可以写信给频道。一些频道在写入几个字节后切换到.isOpen() == false

【问题讨论】:

    标签: java project-reactor reactor-netty


    【解决方案1】:

    我认为这值得一个问题,特别是如果 channel().close() 和 reset() 不起作用。 否则可能是由于默认池和TcpClient.create(opts -> opts.disablePool()) 可能会有所帮助,请告诉我们,如果您有机会在http://github.com/reactor/reactor-netty 上发布问题,您将成为英雄:D

    【讨论】:

    • 同时在 info 上打开日志记录(通过 Slf4j),然后调试 reactor.ipc.netty。它应该在您每次通话后显示非常详细的事件跟踪。
    • opts.disablePool() 没有帮助。我将尝试整理一个用于复制的最小示例并将其归档在 github 上。
    【解决方案2】:

    链接到这个未解决的问题https://github.com/reactor/reactor-netty/issues/15。我们将审核 dispose API。

    【讨论】:

    【解决方案3】:

    以下代码以某种方式破坏了通道,但并未完全破坏。

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

    问题是该通道似乎在服务器端仍然是打开的。 对于基于 NIO2 的服务器,服务器不应测试通道是否为 isOpen()。总是如此。

    作为一种肮脏的解决方法,服务器必须向通道写入两次。如果它在第二次写入时捕获 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);
    }
    

    【讨论】:

      【解决方案4】:

      使用 reactor-core: 3.1.0.M3 和 reactor-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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-15
        • 2019-04-02
        • 2014-07-14
        • 1970-01-01
        • 2018-06-14
        • 1970-01-01
        • 1970-01-01
        • 2016-12-26
        相关资源
        最近更新 更多