我正在编写一个基于Netty的本地HTTP服务器.当我进行压力测试时,我限制在400个请求/秒.
要优化我的服务器,我已经写了基于Netty的一个简单的服务器,只是发送的"Hello World"的客户端,我发起了一个压力测试与加特林2,和与此服务器,我已经得到了同样的结果(限制为400 req/s).
我使用Yourkit进行性能分析,没有额外的GC活动,我的开放/关闭套接字限制为480个套接字/秒.
我使用MacBook Pro,4核,16 GB RAM,我使用Netty 4.1.
我很惊讶地限制在400 req/s,因为其他基准测试的结果显示> 20 000 req/s或更多.我知道有硬件限制,但400 req/s,在4核+ 16 GB Ram上发送"hello World"非常低.
提前感谢您的帮助,我不知道从哪里开始优化我的Netty代码.
是否有任何优化Netty的具体指导方针?
这是我的hello world服务器的源代码,后跟我的连接的处理程序:
public class TestServer { private static final Logger logger = LogManager.getLogger("TestServer"); int nbSockets = 0 ; EventLoopGroup pool = new NioEventLoopGroup() ; private void init(int port) { EventLoopGroup bossGroup = new NioEventLoopGroup(100) ; try { long t1 = System.currentTimeMillis() ; ServerBootstrap b = new ServerBootstrap().group(bossGroup); b.channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("decoder", new HttpRequestDecoder(8192, 8192 * 2, 8192 * 2)); ch.pipeline().addLast("encoder", new HttpResponseEncoder()); ch.pipeline().addLast(new TestServerHandler(TestServer.this)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.err.println("Error"); super.exceptionCaught(ctx,cause); } }) .option(ChannelOption.SO_BACKLOG, 100000) .option(ChannelOption.SO_KEEPALIVE,false) .option(ChannelOption.TCP_NODELAY,false) .option(ChannelOption.SO_REUSEADDR,true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,10000) .childOption(ChannelOption.SO_KEEPALIVE, true); ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);; scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.err.println(nbSockets); nbSockets = 0 ; } },1, 1,TimeUnit.SECONDS) ; // Bind and start to accept incoming connections. ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); System.err.println("Coucou"); } } public static void main(String[] args) { TestServer testServer = new TestServer() ; testServer.init(8888); } }
这是我的处理程序的源代码:
public class TestServerHandler extends ChannelInboundHandlerAdapter { private final TestServer testServer; public TestServerHandler(TestServer testServer) { this.testServer = testServer ; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { process(ctx, msg); } catch (Throwable e) { e.printStackTrace(); } } public void process(ChannelHandlerContext ctx, Object msg) throws Exception { ctx.channel().writeAndFlush(buildHttpResponse()).addListener(new GenericFutureListener>() { @Override public void operationComplete(Future super Void> future) throws Exception { ctx.channel().close() ; testServer.nbSockets ++ ; } }) ; } public DefaultFullHttpResponse buildHttpResponse() { String body = "hello world" ; byte[] bytes = body.getBytes(Charset.forName("UTF-8")); ByteBuf byteContent = Unpooled.copiedBuffer(bytes); HttpResponseStatus httpResponseStatus =HttpResponseStatus.OK; DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, byteContent); return httpResponse; } }
Stephane Lan.. 5
你已经禁用了keep-alive并且正在关闭每个请求的连接,所以我怀疑你花了大部分时间来打开和关闭HTTP连接.
因为其他基准测试的结果显示> 20 000 req/s或更多
您指的是哪些其他基准?很有可能它们都是池连接,并且使用HTTP流水线,因此与您的使用方式截然不同.
回到原来的问题(如何优化Netty),你可以做两件事:
微优化分配:使用池化的ByteBuffers,甚至更好地计算它们一次
切换到本机epoll传输(仅限Linux)
但是所有这些改进与连接处理相比可能不会太多.
你已经禁用了keep-alive并且正在关闭每个请求的连接,所以我怀疑你花了大部分时间来打开和关闭HTTP连接.
因为其他基准测试的结果显示> 20 000 req/s或更多
您指的是哪些其他基准?很有可能它们都是池连接,并且使用HTTP流水线,因此与您的使用方式截然不同.
回到原来的问题(如何优化Netty),你可以做两件事:
微优化分配:使用池化的ByteBuffers,甚至更好地计算它们一次
切换到本机epoll传输(仅限Linux)
但是所有这些改进与连接处理相比可能不会太多.