Java Haproxy+;netty:防止连接重置异常的方法?
我们在netty-3.6运行的后端前面使用haproxy。我们正在处理大量的连接,其中一些可能是长期的 现在的问题是,当haproxy通过重新平衡的方式关闭连接时,它通过发送tcp RST来实现。当netty使用的sun.nio.ch类看到这一点时,它抛出一个IOException:“由对等方重置连接” 跟踪:Java Haproxy+;netty:防止连接重置异常的方法?,java,tcp,netty,nio,haproxy,Java,Tcp,Netty,Nio,Haproxy,我们在netty-3.6运行的后端前面使用haproxy。我们正在处理大量的连接,其中一些可能是长期的 现在的问题是,当haproxy通过重新平衡的方式关闭连接时,它通过发送tcp RST来实现。当netty使用的sun.nio.ch类看到这一点时,它抛出一个IOException:“由对等方重置连接” 跟踪: sun.nio.ch.FileDispatcherImpl.read0(Native Method):1 in "" sun.nio.ch.SocketDispatcher.read(S
sun.nio.ch.FileDispatcherImpl.read0(Native Method):1 in ""
sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39):1 in ""
sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:225):1 in ""
sun.nio.ch.IOUtil.read(IOUtil.java:193):1 in ""
sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:375):1 in ""
org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:64):1 in ""
org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109):1 in ""
org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312):1 in ""
org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90):1 in ""
org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178):1 in ""
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145):1 in ""
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615):1 in ""
java.lang.Thread.run(Thread.java:724):1 in ""
这会导致每个配置出现以下问题:
选项http假装keepalive
这是最有效的方法(因为haproxy似乎用FIN而不是RST关闭了大多数连接),但每台服务器每秒仍会产生大约3个异常。此外,它有效地消除了负载平衡,因为一些传入连接非常长时间,吞吐量非常高:使用假装keepalive,它们永远不会通过haproxy重新平衡到另一台服务器
选项http保持活动状态
由于我们的后端希望保持活动连接真正保持活动(因此不会自行关闭它们),因此此设置相当于每个连接最终都会捕获一个异常,从而导致服务器崩溃。我们尝试添加“首选最后一个服务器”,但没有多大帮助
选项http服务器关闭
这在理论上应该适用于适当的负载平衡,没有例外。然而,在我们的后端服务器响应之后,似乎有一场关于哪一方首先发送其RST的竞赛:haproxy还是我们注册的ChannelFutureListener.CLOSE。实际上,我们仍然会遇到太多异常,服务器也会崩溃
有趣的是,例外情况通常会更多,我们为渠道提供的员工越多。我想它比写作更能加速阅读
无论如何,我已经阅读了netty和haproxy中的不同频道和socketoptions有一段时间了,并没有真正找到任何听起来像解决方案的东西(或者在我尝试它时起作用)。'Connecton reset by peer'通常是由于写入另一端已经关闭的连接而引起的。这会导致对等方发送RST。但几乎可以肯定的是,它已经发出了一条鳍。我会在这里重新检查你的假设。很少有应用程序故意发送RST。您最可能遇到的是应用程序协议错误。如果这是不可避免的,那么EconReset也是如此。Tomcat Nio处理程序只是执行以下操作:
} catch (java.net.SocketException e) {
// SocketExceptions are normal
Http11NioProtocol.log.debug
(sm.getString
("http11protocol.proto.socketexception.debug"), e);
} catch (java.io.IOException e) {
// IOExceptions are normal
Http11NioProtocol.log.debug
(sm.getString
("http11protocol.proto.ioexception.debug"), e);
}
因此,内部sun类(sun.nio.ch.FileDispatcherImpl)的初始抛出似乎是不可避免的,除非您自己重新实现它们。尝试使用
- 选项http隧道
- 无选项重新修补
不确定redispatch,但http隧道解决了我们这边的问题。从haproxy 1.5开始,它现在将
FIN
(FIN,ACK
)发送到后端服务器,而harpoxy 1.4用于发送RST
。在这种情况下,这可能会有所帮助
如果可以找到此文档,我将添加链接…注意:根据我的理解,您不必担心连接重置异常,除非您的一端有一个连接池和保持活动的连接。 在为我们的服务使用HAProxy时,我遇到了一个类似的问题,即大量的连接重置(RST)(根据负载情况,过去在10秒内重置5-20次)
我就是这样修好的 我们有一个系统,其中连接总是保持活动状态(在HTTP连接级别保持活动状态总是正确的。也就是说,一旦建立了连接,我们就将中的此连接重新用于后续调用,而不是创建新的调用。) 现在,根据我的代码调试和TCP转储我发现RST是在下面的场景中从HAProxy抛出的
我们将此配置设置为60秒。因为我们有一个连接池,所以当服务器上的负载减少时,会导致其中一些连接一分钟内无法使用
然后HAProxy使用RST信号关闭这些连接
根据文件:
注意:这不会导致负载平衡器在新服务器上使用以前的服务器进行新连接。新连接的决策始终基于负载平衡算法。此选项仅适用于客户端和服务器之间已处于活动状态的现有连接。
当我使用此选项进行测试时,新连接仍将连接到server2,即使之前的连接已发送到server1