Java NIO Selector可以选择不超过50个SelectionKeys?
我使用
siege对我的手工构建的文件服务器进行压力测试,它适用于小文件(小于1KB),而在使用1MB文件进行测试时,它不能按预期工作.
以下是使用小文件进行测试的结果: neevek@~$siege -c 1000 -r 10 -b http://127.0.0.1:9090/1KB.txt ** SIEGE 2.71 ** Preparing 1000 concurrent users for battle. The server is now under siege.. done. Transactions: 10000 hits Availability: 100.00 % Elapsed time: 9.17 secs Data transferred: 3.93 MB Response time: 0.01 secs Transaction rate: 1090.51 trans/sec Throughput: 0.43 MB/sec Concurrency: 7.29 Successful transactions: 10000 Failed transactions: 0 Longest transaction: 1.17 Shortest transaction: 0.00 以下是使用1MB文件进行测试的结果: neevek@~$siege -c 1000 -r 10 -b http://127.0.0.1:9090/1MB.txt ** SIEGE 2.71 ** Preparing 1000 concurrent users for battle. The server is now under siege...[error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer [error] socket: unable to connect sock.c:222: Connection reset by peer [error] socket: unable to connect sock.c:222: Connection reset by peer [error] socket: unable to connect sock.c:222: Connection reset by peer [error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer [error] socket: unable to connect sock.c:222: Connection reset by peer [error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer [error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer [error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer [error] socket: read error Connection reset by peer sock.c:460: Connection reset by peer 当siege以上述错误终止时,我的文件服务器仍然使用固定数量的WRITABLE SelectionKey旋转,即Selector.select()保持返回固定数字,比如50. 通过上面的测试,在我看来我的文件服务器不能接受不超过50个并发连接,因为当用小文件运行测试时,我注意到服务器选择1或2个SelectionKeys,当运行大文件时,它选择每次最多50个. 我试图在没有帮助的情况下增加Socket.bind()中的积压. 可能是问题的原因是什么? 编辑 更多信息: 当使用1MB文件进行测试时,我注意到siege以Broken管道错误终止,并且文件服务器只接受了198个连接,尽管我指定了1000个并发连接x 10轮(1000 * 10 = 10000)来充斥服务器. 编辑2 我已经使用以下代码测试(单个类)来重现同样的问题,在这段代码中,我只接受连接,我不读或写,siege客户端终止连接重置或连接超时之前的管道错误.我还注意到Selector只能选择少于1000个键.您可以尝试下面的代码来见证问题. public class TestNIO implements Runnable { ServerSocketChannel mServerSocketChannel; Selector mSelector; public static void main(String[] args) throws Exception { new TestNIO().start(); } public TestNIO () throws Exception { mSelector = Selector.open(); } public void start () throws Exception { mServerSocketChannel = ServerSocketChannel.open(); mServerSocketChannel.configureBlocking(false); mServerSocketChannel.socket().bind(new InetSocketAddress(9090)); mServerSocketChannel.socket().setSoTimeout(150000); mServerSocketChannel.register(mSelector,SelectionKey.OP_ACCEPT); int port = mServerSocketChannel.socket().getLocalPort(); String serverName = "http://" + InetAddress.getLocalHost().getHostName() + ":" + port; System.out.println("Server start listening on " + serverName); new Thread(this).start(); } @Override public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); while (true) { int num = mSelector.select(); System.out.println("SELECT = " + num + "/" + mSelector.keys().size()); if (num > 0) { Iterator<SelectionKey> keys = mSelector.selectedKeys().iterator(); while (keys.hasNext()) { final SelectionKey key = keys.next(); if (key.isValid() && key.isAcceptable()) { accept(key); } } // clear the selected keys mSelector.selectedKeys().clear(); } } } catch (Exception e) { e.printStackTrace(); } } private void accept (SelectionKey key) throws IOException { SocketChannel socketChannel = mServerSocketChannel.accept(); socketChannel.configureBlocking(false); socketChannel.socket().setSoTimeout(1000000); socketChannel.socket().setKeepAlive(true); // since we are connected,we are ready to READ socketChannel.register(mSelector,SelectionKey.OP_READ); } } 解决方法
它实际上与为ServerSocketChannel设置的默认积压值相关
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/nio/ch/ServerSocketChannelImpl.java#138 您可以通过将backlog值作为第二个参数传递给bind方法来解决此问题. mServerSocketChannel.socket().bind(new InetSocketAddress(9090),“backlog value”) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |