1.编写服务端代码
public class NettyServer {
public static void main(String [] args){
new NettyServer().run(8000, 8050);
}
public void run(int beginPort, int endPort){
System.out.println("服务端启动中");
//配置服务端线程组
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.SO_REUSEADDR, true);
serverBootstrap.childHandler( new TcpCountHandler());
for(; beginPort < endPort; beginPort++){
int port = beginPort;
serverBootstrap.bind(port).addListener((ChannelFutureListener) future->{
System.out.println("服务端成功绑定端口 port = "+port);
});
}
}
}
2.服务端handler处理类
@ChannelHandler.Sharable
public class TcpCountHandler extends ChannelInboundHandlerAdapter {
private AtomicInteger atomicInteger = new AtomicInteger();
public TcpCountHandler(){
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(()->{
System.out.println("当前连接数为 = "+ atomicInteger.get());
}, 0, 1, TimeUnit.SECONDS);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
atomicInteger.incrementAndGet();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
atomicInteger.decrementAndGet();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("TcpCountHandler exceptionCaught");
cause.printStackTrace();
}
}
3.编写客户端代码
public class NettyClient {
//使用阿里云可以输入自己的 阿里云IP地址
private static final String SERVER = "127.0.0.1";
public static void main(String [] args){
new NettyClient().run(Config.BEGIN_PORT, Config.END_PORT);
}
public void run(int beginPort, int endPort){
System.out.println("客户端启动中");
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_REUSEADDR, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
}
});
int index = 0 ;
int finalPort ;
while (true){
finalPort = beginPort + index;
try {
bootstrap.connect(SERVER, finalPort).addListener((ChannelFutureListener)future ->{
if(!future.isSuccess()){
System.out.println("创建连接失败 " );
}
}).get();
} catch (Exception e) {
//e.printStackTrace();
}
++index;
if(index == (endPort - beginPort)){
index = 0 ;
}
}
}
}
4.修改虚拟机或者阿里云linux内核参数(centos6.5/centos7.0)
局部文件句柄限制(单个进程最大文件打开数)
使用 ulimit -n 一个进程最大打开的文件数 fd
不同系统有不同的默认值
root身份编辑 vim /etc/security/limits.conf
增加下面
root soft nofile 1000000
root hard nofile 1000000
* soft nofile 1000000
* hard nofile 1000000
* 表示当前用户,修改后要重启
全局文件句柄限制(所有进程最大打开的文件数,不同系统是不一样,可以直接echo临时修改)
查看命令
cat /proc/sys/fs/file-max
永久修改全局文件句柄
vim /etc/sysctl.conf
增加 fs.file-max = 1000000
修改后生效 sysctl -p
5. 启动(修改jvm虚拟机的参数)
java -jar millionServer-1.0-SNAPSHOT.jar -Xms5g -Xmx5g -XX:NewSize=3g -XX:MaxNewSize=3g
6.注意事项
使用虚拟机测试的时候,建议虚拟机为内存为8G以上。