暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【Netty】网络连接数上限造成的问题

左羊公社 2022-12-11
2260

Netty Socket压测报:Address already in use: no further information




最近左羊在做Netty Socket压力测试时,客户端连接数每次加压到4千左右时便会报出上述错误,特以此文记录下原因及解决方案。


环境介绍

    Windows 10
    JDK 1.8
    Netty 4.1.18.Final


    代码示例

    服务端

      package cn.zy.testoneconnectionsnumber.netty_socket_server;
      import cn.zy.testoneconnectionsnumber.ConvertCode;
      import io.netty.bootstrap.ServerBootstrap;
      import io.netty.channel.*;
      import io.netty.channel.nio.NioEventLoopGroup;
      import io.netty.channel.socket.SocketChannel;
      import io.netty.channel.socket.nio.NioServerSocketChannel;
      import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
      import io.netty.handler.codec.LengthFieldPrepender;
      import io.netty.handler.codec.bytes.ByteArrayDecoder;
      import io.netty.handler.codec.bytes.ByteArrayEncoder;
      import io.netty.handler.codec.string.StringDecoder;
      import io.netty.handler.codec.string.StringEncoder;
      import io.netty.util.CharsetUtil;
      import io.netty.util.concurrent.DefaultThreadFactory;
      public class NettyServer {
      public static void main(String[] args) {
      NioEventLoopGroup bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("Server1", true));
      NioEventLoopGroup wokerGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("Server1", true));
      try{
      ServerBootstrap bootstrap = new ServerBootstrap();
      bootstrap.group(bossGroup,wokerGroup)
      .channel(NioServerSocketChannel.class)
      .childHandler(new ChannelInitializer<SocketChannel>() {
      @Override
      protected void initChannel(SocketChannel socketChannel) throws Exception {
      ChannelPipeline pipeline = socketChannel.pipeline();
      pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
      pipeline.addLast(new LengthFieldPrepender(4));
      pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
      pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
      pipeline.addLast(new SimpleChannelInboundHandler<String>() {
      @Override
      protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception {
      System.out.println(msg);
      channelHandlerContext.channel().writeAndFlush("Hello Netty Clinet!");
      }
      });
      }
      });
      //绑定端口号
      ChannelFuture channelFuture = bootstrap.bind(9999).sync();
      channelFuture.channel().closeFuture().sync();
      } catch (InterruptedException e) {
      e.printStackTrace();
      } finally {
      bossGroup.shutdownGracefully();
      wokerGroup.shutdownGracefully();
      }
      }
      }

      客户端

        package cn.zy.testoneconnectionsnumber.netty_socket_client;
        import io.netty.bootstrap.Bootstrap;
        import io.netty.channel.*;
        import io.netty.channel.nio.NioEventLoopGroup;
        import io.netty.channel.socket.SocketChannel;
        import io.netty.channel.socket.nio.NioSocketChannel;
        import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
        import io.netty.handler.codec.LengthFieldPrepender;
        import io.netty.handler.codec.string.StringDecoder;
        import io.netty.handler.codec.string.StringEncoder;
        import io.netty.util.CharsetUtil;
        import io.netty.util.concurrent.DefaultThreadFactory;
        import java.time.LocalDateTime;
        public class NettyClient {
        public static void main(String[] args) {
        NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("client1", true));
        for (int i = 0; i < 6000; i++) {
        int finalI = i;
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
        .handler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
        pipeline.addLast(new LengthFieldPrepender(4));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
        pipeline.addLast(new SimpleChannelInboundHandler<String>() {
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception {
        System.out.println(msg);
        channelHandlerContext.writeAndFlush(LocalDateTime.now());
        channelHandlerContext.close();
        }
        @Override
        public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {
        channelHandlerContext.writeAndFlush(finalI + "Hello Netty Server!");
        }
        });
        }
        });
        try {
        ChannelFuture channelFuture = bootstrap.connect("localhost", 9999).sync();
        channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        }
        }
        }


        造成原因

        原因是Windows的默认最大TCP连接端口数(MaxUserPort)是5000,默认240秒释放之前的操作完的等待线程。由此造成本机开发环境压力测试,连接数达到3-4千时报错。


        解决步骤

          1、打开注册表:regedit(开始-运行-输入regedit,win+R - 输入regedit)。
          2、\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters。
          3、新建 DWORD值,name:TcpTimedWaitDe,value:30(十进制) –> 设置为30秒,默认是240秒。
          4、新建 DWORD值,name:MaxUserPort,value:65534(十进制) –> 设置最大连接数65534,Windows的默认最大TCP连接端口数(MaxUserPort)是5000。
          5、重启系统。


          参考文献

            码农教程 . http://www.manongjc.com/detail/27-wgzlsxgoyaywiiz.html . 超出TCP连接端口数限制(MaxUserPort)引起的服务器问题
            博客园 . https://www.cnblogs.com/ngd-mzl/p/16409901.html . jmeter 性能测试 报错信息“address already in use:connect”解决方法
            张彦飞 . 深入理解Linux网络 . 第八章 一台机器最多支持多少条TCP链接

            感谢你的观看,如果有解决到你的问题麻烦【点赞】【关注】鼓励一下,YES!


            文章转载自左羊公社,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论