Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 慢网性能_Java_Netty - Fatal编程技术网

Java 慢网性能

Java 慢网性能,java,netty,Java,Netty,我正在使用netty从服务器下载大文件。在使用jmeter运行性能测试时,我发现我的服务器提供了非常高的吞吐量,直到150个并发用户,但一旦并发用户数量增加,它就开始下降,几乎是500个并发用户的一半 NettyServer- ServerBootstrap b = new ServerBootstrap(); EpollEventLoopGroup bossGroup = new EpollEventLoopGroup(); EpollEventLoopGroup worker

我正在使用netty从服务器下载大文件。在使用jmeter运行性能测试时,我发现我的服务器提供了非常高的吞吐量,直到150个并发用户,但一旦并发用户数量增加,它就开始下降,几乎是500个并发用户的一半

NettyServer-

ServerBootstrap b = new ServerBootstrap();
    EpollEventLoopGroup bossGroup = new EpollEventLoopGroup();
    EpollEventLoopGroup workerGroup = new EpollEventLoopGroup();
  try {
        b.group(bossGroup, workerGroup).channel(EpollServerSocketChannel.class).handler(new LoggingHandler(LogLevel.DEBUG)).childHandler(new FileServerInitializer());
        Channel ch = b.bind(port).sync().channel();
        ch.closeFuture().sync();

    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
        FileServerHandler.threadPool.shutdownNow();
    }
文件服务器初始值设定项-

ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast("decoder", new HttpRequestDecoder());
    pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
    pipeline.addLast("encoder", new HttpResponseEncoder());
    pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
    pipeline.addLast("handler", (ChannelHandler) new FileServerHandler());
}
文件服务器处理程序-

    RandomAccessFile raf;
    try {
        raf = new RandomAccessFile(file, "r");
    } catch (FileNotFoundException ignore) {
        sendError(ctx, HttpResponseStatus.NOT_FOUND);
        return;
    }
    response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK);
    response.headers().set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileNameType);
    response.headers().set(HttpHeaders.CONTENT_LENGTH, String.valueOf(size));

    ctx.write(response);
    ChannelFuture sendFileFuture;
    ChannelFuture lastContentFuture;
    sendFileFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, size, 8192)),ctx.newProgressivePromise());
    lastContentFuture = sendFileFuture; 
    sendFileFuture.addListener(new ChannelProgressiveFutureListener() {

        public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
            if (total < 0) {            
                System.out.println(future.channel() + " Transfer progress: " + progress);
            }else {
                System.out.println(future.channel() + " Transfer progress: " + progress + " / " + total);
            }
        }

        public void operationComplete(ChannelProgressiveFuture future) {
            System.out.println(future.channel() + " Transfer complete.");
        }
    });

    lastContentFuture.addListener(ChannelFutureListener.CLOSE);
随机存取文件raf;
试一试{
raf=新随机访问文件(文件“r”);
}捕获(FileNotFoundException忽略){
sendError(未找到ctx、HttpResponseStatus.NOT_);
返回;
}
response=newdefaulthttpresponse(HTTP_1_1,HttpResponseStatus.OK);
response.headers().set(HttpHeaders.CONTENT_处置,“附件;文件名=“+fileNameType”);
response.headers().set(HttpHeaders.CONTENT_LENGTH,String.valueOf(size));
写(应答);
渠道未来发送文件未来;
渠道未来;内容未来;
sendFileFuture=ctx.writeAndFlush(新的HttpChunkedInput(新的ChunkedFile(raf,0,size,8192)),ctx.newProgressivePromise());
lastContentFuture=sendFileFuture;
sendFileFuture.addListener(新通道ProgressiveFutureListener(){
公共无效运营进展(渠道进展未来、长期进展、长期总计){
如果(总数<0){
System.out.println(future.channel()+“传输进度:”+进度);
}否则{
System.out.println(future.channel()+“传输进度:”+进度+“/”+总计);
}
}
公共无效操作完成(渠道进展未来){
System.out.println(future.channel()+“传输完成”);
}
});
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
有人能告诉我为什么会发生这种情况吗?

您也可以尝试:

  • 例如,更改网络端的子属性(获取自己的正确值)

  • 调整BOSS和WORKER端的线程数(默认值为2N+1,其中N是BOSS的核心数,如果我没有记错的话)

    我通常为Boss设置2N+1,为Worker设置10N+1(将Worker视为异步Worker,这意味着这不是对并发客户端的真正限制,而只是对“真正的”并发客户端,这意味着它们实际上做了一些事情)。在Linux上,请小心相应地增加文件描述符限制

  • 更精确地指定辅助线程级别


  • 当然,也可以参考其他建议

    服务器必须处理的并发请求越多,需要的管理(簿记、上下文切换等)就越多,这将消耗您的资源。此外,您最终将达到资源上限,例如CPU、内存、带宽等,这将限制整个进程,并降低吞吐量/用户。@Thomas:我已经使用jmx/visualVM完成了评测。使用的最大内存为4GB中的1.5GB,最大CPU为20%。关于带宽,我正在通过10gig管道上的LAN下载内容。对于允许的并发请求数量,可能仍有一些限制,因此服务器将暂停任何多余的请求,直到释放插槽为止。还要注意,内存和cpu使用率并不是限制应用程序的唯一资源。可能是磁盘io、文件句柄数、线程数等,或者您的应用程序/vm由于某种原因没有使用所有CPU。您可能希望分析应用程序并查看它从何处开始变慢,即测量代码部分的执行频率以及这些部分的运行方式。尝试使用发送文件的方法发送文件以减少内存瓶颈:@Ferrybig:如前所述,没有内存瓶颈。我们有8GB的虚拟机,其中只有700MB-1GB得到利用。我也试过,但结果还是一样的。
    bootstrap.channel(NioServerSocketChannel.class);
    bootstrap.group(groupBoss, groupWorker);
    bootstrap.option(ChannelOption.TCP_NODELAY, true);
    bootstrap.option(ChannelOption.SO_REUSEADDR, true);
    bootstrap.option(ChannelOption.SO_LINGER, 0);
    bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
    bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
    bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
    bootstrap.childOption(ChannelOption.SO_LINGER, 0);
    bootstrap.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout);
    bootstrap.childOption(ChannelOption.SO_RCVBUF, 1048576);
    bootstrap.childOption(ChannelOption.SO_SNDBUF, 1048576);
    bootstrap.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 10*65536);
    bootstrap.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, 2*65536);
    bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);