得到ClosedChannelException,因为在关闭之后写入频道

时间:2014-11-05 02:45:45

标签: java netty apache-zookeeper

我们的架构要求有两个并发工作流程:

  1. 将内容写入netty处理程序之外的netty频道。
  2. netty正常生命周期。 (连接,关闭,重新连接..)
  3. 我们得到了ClosedChannelException,它似乎通过查看堆栈跟踪(Netty 3.7)来向执行者线程池传播错误。

    java.nio.channels.ClosedChannelException
    at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:265)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:456)
    at org.jboss.netty.channel.socket.nio.SocketSendBufferPool$UnpooledSendBuffer.transferTo(SocketSendBufferPool.java:203)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.write0(AbstractNioWorker.java:202)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromTaskLoop(AbstractNioWorker.java:152)
    at org.jboss.netty.channel.socket.nio.AbstractNioChannel$WriteTask.run(AbstractNioChannel.java:335)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:366)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:290)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
    

    我的问题是:

    1. 它是否真的破坏了执行程序线程池?我担心的情况:。如果可以的话,我会重新设计代码(糟糕的遗留代码)。让我更清楚地解释一下我担心的情况:一些数据被写入旧的封闭通道(由于异步行为而未实际写入) - >通过重新连接到另一个地址来创建新频道 - >由于异步属性,数据实际写入旧通道。
    2. 如何在关闭和写入netty频道时处理这种并发?

2 个答案:

答案 0 :(得分:2)

  

它是否真的破坏了执行程序线程池?

没有

看来您的代码(可能是“将内容写入netty处理程序之外的netty频道”的东西)已经将频道关闭到了早期。 (正如@EJP评论的那样,这是你的代码中的一个错误......)

这不会破坏工作线程,但可能导致客户端发送了不完整的响应。

  

我担心的情况:一些写入旧封闭通道的数据和一个新创建的通道(重新连接到另一个地址),ClosedChannelException会搞砸吗?

旧的封闭频道与新频道无关。

  

如何在关闭和写入netty频道时处理这种并发?

重新设计您的代码,以便只有正常的Netty“工作流程”才会关闭频道。使两个“工作流程”共同负责关闭是一个问题的处方,特别是因为其中一个(正常的Netty工作流程)被硬编码为认为问题仅适用于它。

答案 1 :(得分:-1)

如果我是正确的,你也可以在自己的处理程序中获得异常。 我在处理程序中有这样的异常处理,因为出于多种原因可能会发生关闭连接,至少例如因为线路已断开连接(因此没有Netty或应用程序逻辑错误)。关闭的正常事件可能发生在您尝试向通道提交写入和异常之间。 在我的应用程序逻辑中,我考虑到了这一点,例如尝试重新连接,或者至少通过清理已关闭连接的上下文。

对我来说,这不是一个错误,但Netty必须通知您,您的应用程序处理程序对通道进行了关闭。