我正在使用netty从服务器下载大文件。在使用 jmeter 运行性能测试时,我发现我的服务器在 150 个并发用户之前提供了非常高的吞吐量,但是一旦并发用户数量增加,它就会开始下降,几乎变成了 500 个并发用户的一半。
网络服务器 -
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);
谁能告诉我为什么会这样?
您也可以尝试:
-
例如,更改网络端的子属性(获取自己的正确值)
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);
-
调整 BOSS 和 WORKER 端的线程数(默认值为 2N+1,如果我没记错的话,N 是 Boss 的核心数字)
我通常为 Boss 设置 2N+1,为 Worker 设置 10N+1(将 Worker 视为异步工作线程,这意味着这不是对并发客户端的真正限制,而只是在"真正的"并发客户端上,这意味着它们实际上做了一些事情)。在 Linux 上要小心,以相应地增加文件描述符限制。
-
更精确地指定工作线程级别
当然,也可以看到其他建议