6

私は、Java Netty を使用して高負荷の tcp アプリケーションに取り組んでいます。これは、300k の同時 TCP 接続に到達することを期待しています。

テスト サーバーでは完璧に動作し、300k の接続に到達しますが、実稼働サーバーにデプロイすると、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

クライアント 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

OS リリースは、カーネル 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 とメモリは低レベルを維持しています。すべて問題ないように見えます。クライアントからサーバーが接続をリセットしただけです。

2.6.32 カーネルを搭載した SUSE Linux Enterprise Server 11 SP1 のテスト サーバーがあり、問題なく動作し、最大 300k の接続をサポートできます。

おそらくカーネルまたはセキュリティの制限がこれを引き起こしていると思いますが、サーバーがRSTを送信する理由のデバッグ情報を取得するための提案や方法が見つかりませんか? ありがとう。

4

2 に答える 2

1

最後に根本原因を突き止めました。簡単に言うと、これは JDK のバグでした。http ://mail.openjdk.java.net/pipermail/nio-dev/2013-September/002284.htmlを参照してください 。fd > 64 * 1024 の場合に NPE が発生します。

JDK7_45 にアップグレードした後、すべてがうまく機能するようになりました。

于 2013-11-25T02:55:02.613 に答える