Netty实现单机百万连接和应用级别性能调优
如何模拟Ntty百万连接
通常启动一个服务端会绑定一个端口例如 8000,当客户端去连接端口是有限制的最大是65535加上默认1024及以下的端口,就剩下1024-65535再扣除一些常用的端口,实际可用端口只有6W左右。那么如何实现单机百万连接?
我们在服务端启动例如 8000-8100 这100个端口,100*6W这样就可以连接600W左右的连接,这里是TPC的一个基础的知识,虽然对于客户端来说是同一个端口号,但是对于Server是不同的端口号,由于TCP是一个私源组概念,也就是说它是由源IP源端口号加上目的IP目的端口号为确定的,当你源IP和源端口号是一样的但是你目的端口号不一样那么最终系统底层会把它当做两条TCP连接来处理,所以说我们这里取了个巧开了Server开启了100个端口号,这就是我们单机百万连接的准备工作,接下来看一下代码的实现
统计时间Hanlder
@Sharable
public class ConnectionCountHandler extends ChannelInboundHandlerAdapter {
private AtomicInteger nConnection = new AtomicInteger();
public ConnectionCountHandler() {
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
System.out.println("connections: " + nConnection.get());
}, 0, 2, TimeUnit.SECONDS);
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
nConnection.incrementAndGet();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
nConnection.decrementAndGet();
}
}
public class Constant {
static final int BEGIN_PORT = 8000;
static final int N_PORT = 100;
}
服务端
public final class Server {
public static void main(String[] args) {
new Server().start(BEGIN_PORT, N_PORT);
}
public void start(int beginPort, int nPort) {
System.out.println("server starting....");
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
bootstrap.childHandler(new ConnectionCountHandler());
for (int i = 0; i < nPort; i++) {
int port = beginPort + i;
bootstrap.bind(port).addListener((ChannelFutureListener) future -> {
System.out.println("bind success in port: " + port);
});
}
System.out.println("server started!");
}
}
客户端
public class Client {
private static final String SERVER_HOST = "192.168.1.42";
public static void main(String[] args) {
new Client().start(BEGIN_PORT, N_PORT);
}
public void start(final int beginPort, int nPort) {
System.out.println("client starting....");
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.SO_REUSEADDR, true);