当TCP连接超过65000个时,服务器会向客户端发送RST。

6

我正在使用Java Netty开发一款高负载的TCP应用程序,预计将支持30万个并发TCP连接。

在测试服务器上,它可以完美地工作,支持30万个连接。但是当部署到生产服务器时,它只能支持65387个连接。在达到这个数字后,客户端会抛出"java.io.IOException: Connection reset by peer"异常。我尝试了很多次,每次当连接数达到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

客户端进行第三次握手后,服务器向客户端发送了一个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

最大打开文件描述符已经设置为999999

linux-152k:~ # ulimit -n
999999

操作系统版本为SUSE Linux Enterprise Server 11 SP2,内核版本为3.0.13:

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内核。我猜可能是由于不同的内核版本引起的。将会获取更多的服务器进行测试,并在有所发现时进行更新。 - Santal Li
您是否尝试在单个客户端机器的单个NIC上创建超过64k个连接?如果是这样,那是不可能的。您可以尝试将连接分散到多个客户端机器(或多个NIC)上吗?这可能只是客户端机器断开连接的原因。 - trustin
有5台客户端机器,它们中的每一台都创建了60000个到服务器的连接。我确定这不是客户端断开连接,无论如何还是谢谢。 - Santal Li
2个回答

1

谢谢,我已经查看了链接,它提到了文件描述符限制,但在我的服务器上已经设置为999999。 - Santal Li

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接