【问题标题】:Server send RST to client when TCP connection max than 65000~当 TCP 连接最大超过 65000 时,服务器向客户端发送 RST~
【发布时间】:2013-11-04 08:10:05
【问题描述】:

我正在使用 Java Netty 开发一个高负载的 tcp 应用程序,它预计会到达 300k 并发 TCP 连接。

在测试服务器上完美运行,到达300k连接,但是部署到生产服务器时,它只能支持65387个连接,到达这个数字后,客户端会抛出“java.io.IOException:对等连接重置”例外。我试了很多次,每次当连接数达到65387时,客户端将无法创建连接。

网络捕获如下,10.95.196.27是服务器,10.95.196.29是客户端:

16822   12:26:12.480238 10.95.196.29    10.95.196.27    TCP 74  can-ferret > http [SYN] Seq=0 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=872641174 TSecr=0 WS=128
16823   12:26:12.480267 10.95.196.27    10.95.196.29    TCP 66  http > can-ferret [SYN, ACK] Seq=0 Ack=1 Win=2920 Len=0 MSS=1460 SACK_PERM=1 WS=1024
16824   12:26:12.480414 10.95.196.29    10.95.196.27    TCP 60  can-ferret > http [ACK] Seq=1 Ack=1 Win=14720 Len=0
16825   12:26:12.480612 10.95.196.27    10.95.196.29    TCP 54  http > can-ferret [FIN, ACK] Seq=1 Ack=1 Win=3072 Len=0
16826   12:26:12.480675 10.95.196.29    10.95.196.27    HTTP    94  Continuation or non-HTTP traffic
16827   12:26:12.480697 10.95.196.27    10.95.196.29    TCP 54  http > can-ferret [RST] Seq=1 Win=0 Len=0

客户端3与服务器握手后,服务器向客户端发送RST包,新连接断开导致的异常。

客户端异常堆栈如下:

16:42:05.826 [nioEventLoopGroup-1-15] WARN  i.n.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the end of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method) ~[na:1.7.0_25]
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) ~[na:1.7.0_25]
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:225) ~[na:1.7.0_25]
    at sun.nio.ch.IOUtil.read(IOUtil.java:193) ~[na:1.7.0_25]
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:375) ~[na:1.7.0_25]
    at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:259) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:885) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:226) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:72) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:460) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:424) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:360) ~[netty-all-4.0.0.Beta3.jar:na]
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:103) ~[netty-all-4.0.0.Beta3.jar:na]
    at java.lang.Thread.run(Thread.java:724) ~[na:1.7.0_25]

服务器端没有异常。

我曾尝试将一些 sysctl 项目如下所示以支持巨大的连接,但它没有用:

net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 4096 33554432
net.ipv4.tcp_wmem = 4096 4096 33554432
net.ipv4.tcp_mem = 786432 1048576 26777216
net.ipv4.tcp_max_tw_buckets = 360000
net.core.netdev_max_backlog = 4096
vm.min_free_kbytes = 65536
vm.swappiness = 0
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_syn_backlog = 4096
net.netfilter.nf_conntrack_max = 3000000
net.nf_conntrack_max = 3000000
net.core.somaxconn = 327680

最大打开 fd 已设置为 999999

linux-152k:~ # ulimit -n
999999

操作系统版本是带有 3.0.13 内核的 SUSE Linux Enterprise Server 11 SP2:

linux-152k:~ # cat /etc/SuSE-release 
SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 2
linux-152k:~ # uname -a
Linux linux-152k 3.0.13-0.27-default #1 SMP Wed Feb 15 13:33:49 UTC 2012 (d73692b) x86_64 x86_64 x86_64 GNU/Linux.

dmesg 没有任何错误信息,CPU 和内存保持低电平,一切看起来都很好,只是服务器从客户端重置连接。

我们有一个测试服务器,它是 SUSE Linux Enterprise Server 11 SP1,内核为 2.6.32,运行良好,最多可支持 300k 连接。

我认为可能是某些内核或安全限制导致了这种情况,但我找不到它,任何建议或任何方式来获取服务器为什么发送 RST 的一些调试信息?谢谢。

【问题讨论】:

  • 对此仍然没有任何想法。刚刚发现了一些额外的信息。在另一台测试服务器上,一切正常,达到 300000 个连接,这是一个 linux2.6 内核。我想可能是由不同的内核版本引起的。将获得更多服务器进行测试,如果有什么东西更新。
  • 您是否尝试在单个客户端计算机的单个 NIC 上创建超过 64k 的连接?如果是这样,那是不可能的。您可以尝试将连接分布在多个客户端计算机(或多个 NIC)上吗?它可能只是断开连接的客户端计算机。
  • 有 5 台客户端计算机,每台计算机创建 60000 个与服务器的连接。我确定这不是客户端丢弃连接,无论如何,谢谢。

标签: tcp linux-kernel netty suse


【解决方案1】:

Santal,我刚刚看到以下链接,它似乎可以回答您的问题: What is the theoretical maximum number of open TCP connections that a modern Linux box can have

【讨论】:

  • 谢谢,我查看了链接,它提到了 fd 限制,它已经在我的服务器中设置为 999999。
【解决方案2】:

终于找到了根本原因。简单来说就是JDK的bug,请参考http://mail.openjdk.java.net/pipermail/nio-dev/2013-September/002284.html 当 fd > 64 * 1024 时会导致 NPE。

升级到 JDK7_45 后,现在一切正常。

【讨论】:

    猜你喜欢
    • 2016-08-20
    • 1970-01-01
    • 2013-12-17
    • 2021-08-12
    • 1970-01-01
    • 2017-07-10
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多