I am trying to test the scalability of a Java Vert.x webserver (which is based on Netty) on Mac OS X. For that, I have increased the connection limit to 1 million:
sudo sysctl -w kern.maxfiles=1000200
sudo sysctl -w kern.maxfilesperproc=1000100
sudo ulimit -n 1000000
Then I have created localhost aliases with:
for i in `seq 200 250`; do sudo ifconfig lo0 alias 172.16.123.$i ; done
I am now able to connect to these IP addresses; however, after around 1000-2000 established connections I get "Connection reset by peer" connections:
java.net.SocketException: Connection reset by peer
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:712)
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:191)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:228)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
They are followed by "Too many open files" exceptions:
Caused by: java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:393)
at sun.nio.ch.Net.socket(Net.java:386)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:104)
at sun.nio.ch.SelectorProviderImpl.openSocketChannel(SelectorProviderImpl.java:60)
at java.nio.channels.SocketChannel.open(SocketChannel.java:145)
at io.netty.channel.socket.nio.NioSocketChannel.newSocket(NioSocketChannel.java:48)
Interestingly, when I list all connections with netstat then I see that there are a lot of connections in the FIN_WAIT_1 state:
tcp4 0 213 172.16.123.230.55618 172.16.123.230.8877 FIN_WAIT_1
tcp4 0 213 172.16.123.229.55624 172.16.123.229.8877 FIN_WAIT_1
tcp4 0 213 172.16.123.228.55617 172.16.123.228.8877 FIN_WAIT_1
tcp4 0 213 172.16.123.227.55616 172.16.123.227.8877 FIN_WAIT_1
tcp4 0 213 172.16.123.226.55612 172.16.123.226.8877 FIN_WAIT_1
Other results:
$ netstat -a | wc -l:
14282
$ lsof | wc -l
6922
Server code (simplified):
HttpServer server = vertx.createHttpServer();
server.websocketHandler(ws -> {
connections++;
ws.exceptionHandler(t -> t.printStackTrace());
ws.closeHandler(h -> {
connections--;
});
if (ws.path().equals("/app")) {
ws.dataHandler(data -> {
// ...
});
} else {
ws.reject();
}
}).listen(8877);
Client code (simplified):
Handler<Void> connectHandler = new Handler<Void>() {
@Override
public void handle(Void e) {
HttpClient client = vertx.createHttpClient().setHost(nextHost()).setPort(8877);
client.connectWebsocket("/app", ws -> {
connections++;
ws.exceptionHandler(t -> t.printStackTrace());
ws.closeHandler(h -> {
connections--;
});
// ...
});
if (connections < 1000000) {
vertx.runOnContext(this);
}
}
};
connectHandler.handle(null);
Both started with (on the same computer):
vertx run Class -cp classes:... -instances 8
Does anybody have an idea what could be the problem? I am not yet experienced with such setups and maybe I have just made a simple mistake. It doesn't help to increase the accept backlog.
Further information:
Update:
After adding
limit maxfiles 1000100 2000200
to /etc/launchd.conf and
kern.maxfiles=2000400
kern.maxfilesperproc=1000200
to /etc/sysctl.conf and restarting the computer, it has gotten already a little bit better. However, after I while I get now "Too many open files" exceptions even for reading normal files although there are not more than 10000 open files:
Caused by: sun.nio.fs.UnixException: Too many open files
at sun.nio.fs.UnixNativeDispatcher.getcwd(Native Method)
at sun.nio.fs.UnixFileSystem.<init>(UnixFileSystem.java:67)
at sun.nio.fs.BsdFileSystem.<init>(BsdFileSystem.java:41)
at sun.nio.fs.MacOSXFileSystem.<init>(MacOSXFileSystem.java:44)
at sun.nio.fs.MacOSXFileSystemProvider.newFileSystem(MacOSXFileSystemProvider.java:45)
at sun.nio.fs.MacOSXFileSystemProvider.newFileSystem(MacOSXFileSystemProvider.java:38)
at sun.nio.fs.UnixFileSystemProvider.<init>(UnixFileSystemProvider.java:56)
at sun.nio.fs.BsdFileSystemProvider.<init>(BsdFileSystemProvider.java:36)
at sun.nio.fs.MacOSXFileSystemProvider.<init>(MacOSXFileSystemProvider.java:40)
Update 2:
I have tried several other options as well but it seems like there is a limit at exactly 10180 connections which cannot be exceeded. Unless somebody has another idea, I will probably just switch to linux.
Update 3:
After adding the JVM option "-XX:-MaxFDLimit" I can now open 16331 connections until I get the following exceptions:
java.net.BindException: Can't assign requested address
at sun.nio.ch.Net.connect0(Native Method)
at sun.nio.ch.Net.connect(Net.java:435)
at sun.nio.ch.Net.connect(Net.java:427)
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:643)
at io.netty.channel.socket.nio.NioSocketChannel.doConnect(NioSocketChannel.java:176)
This is probably because of the default portrange (16383 ports):
net.inet.ip.portrange.first: 49152
net.inet.ip.portrange.last: 65535
However, since I use 50 localhost alises I would have expected to be able to open up to 16383 * 50 = 819150 connections. Or is it a known limitation that you cannot use the same port for different aliases?
Update 4:
I have tried to create virtual interfaces with networksetup but the result is the same:
for i in `seq 200 250`; do sudo networksetup -createnetworkservice lo$i lo0 ; sudo networksetup -setmanual lo$i 172.16.123.$i 255.240.0.0 ; done
Add this to your JVM options:
-XX:- MaxFDLimit
per https://developer.apple.com/library/mac/documentation/Java/Reference/Java_VMOptionsRef/Articles/JavaVirtualMachineOptions.html
Originally answered here: Java file limit on OSX lower than in bash
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With