Java Haproxy+;netty:防止连接重置异常的方法?

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

我们在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(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抛出的

  • 当HAProxy的或已到达时,在空闲连接上。
    我们将此配置设置为60秒。因为我们有一个连接池,所以当服务器上的负载减少时,会导致其中一些连接一分钟内无法使用
    然后HAProxy使用RST信号关闭这些连接

  • 当HAProxy未设置时。
    根据文件:

  • 真正的用途是将保持活动的连接发送到服务器。当这 选项时,haproxy将尝试重新使用 连接到服务器,而不是重新平衡到另一台服务器, 导致连接关闭

    由于未设置此选项,因此每次从池中重新使用连接时,HAProxy都会使用RST信号关闭此连接,并创建到其他服务器的新连接(因为我们的负载平衡器设置为循环)这会把整个连接池搞得一团糟,变得毫无用处。

    因此,运行良好的配置:

  • :因此将重新使用与服务器的现有连接
    注意:这不会导致负载平衡器在新服务器上使用以前的服务器进行新连接。新连接的决策始终基于负载平衡算法。此选项仅适用于客户端和服务器之间已处于活动状态的现有连接。
    当我使用此选项进行测试时,新连接仍将连接到server2,即使之前的连接已发送到server1
  • 最小连接:使用循环保持活动,可能会出现到单个服务器的连接倾斜。(假设只有两台服务器,当一台服务器由于部署而停机时,所有新连接都将开始连接到另一台服务器。因此,即使在server2出现时,round robin仍会将新请求一个分配给server1,另一个分配给server2。尽管server1末端有很多连接。因此服务器的负载永远不会完全平衡。
  • 将HAProxy's或设置为10分钟。这增加了数额