[英]Netty as High Performant Http Server to Handle ~2-3 Million Requests/Sec
We are trying to Solve the Problem of Handling Huge Volume of Http POST Requests, and while using Netty Server, I was able to handle only ~50K requests/sec
which is too low. 我们正在尝试解决处理大量Http POST请求的问题,并且在使用Netty Server时,我只能处理
~50K requests/sec
,这太低了。
My question is how to tune this Server to ensure to handle > 1.5 million requests/second
? 我的问题是如何调整此服务器以确保处理
> 1.5 million requests/second
?
Netty4 Server Netty4服务器
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new HttpServerInitializer(sslCtx));
Channel ch = b.bind(PORT).sync().channel();
System.err.println("Open your web browser and navigate to " +
(SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/');
ch.closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
Initializer 初始化
public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {
private final SslContext sslCtx;
public HttpServerInitializer(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
p.addLast(new HttpServerCodec());
p.addLast("aggregator", new HttpObjectAggregator(Integer.MAX_VALUE));
p.addLast(new HttpServerHandler());
}
}
Handler 处理器
public class HttpServerHandler extends ChannelInboundHandlerAdapter {
private static final String CONTENT = "SUCCESS";
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest) msg;
final FullHttpRequest fReq = (FullHttpRequest) req;
Charset utf8 = CharsetUtil.UTF_8;
final ByteBuf buf = fReq.content();
String in = buf.toString( utf8 );
System.out.println(" In ==> "+in);
buf.release();
if (HttpHeaders.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE));
}
in = null;
if (HttpHeaders.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
}
boolean keepAlive = HttpHeaders.isKeepAlive(req);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(CONTENT.getBytes()));
response.headers().set(CONTENT_TYPE, "text/plain");
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
} else {
response.headers().set(CONNECTION, Values.KEEP_ALIVE);
ctx.write(response);
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
{
cause.printStackTrace();
ctx.close();
}
}
Your question is very generic. 你的问题非常通用。 However, I'll try to give you an answer regarding the netty optimizations and your code improvements.
但是,我将尝试为您提供有关netty优化和代码改进的答案。
Your code issues: 您的代码问题:
System.out.println(" In ==> "+in);
- you shouldn't use this in high load cocurrent handler. println
method is synchronized and thus gives penalties to your performance; println
方法中的代码是同步的,因此会对您的性能造成惩罚; HttpRequest
and to FullHttpRequest
. HttpRequest
和FullHttpRequest
。 You may use just last one; Netty specific issues in your code: 代码中的Netty特定问题:
EventLoopGroup bossGroup = new NioEventLoopGroup();
- you need to correctly setup sizes of bossGroup
and workerGroup
groups. bossGroup
和workerGroup
组的大小。 Depending on your test scenarios. new HttpObjectAggregator(Integer.MAX_VALUE)
- you actually don't need this handler in your code. new HttpObjectAggregator(Integer.MAX_VALUE)
- 实际上你的代码中不需要这个处理程序。 So for better performance, you may remove it. new HttpServerHandler()
- you don't need to create this handler for every channel. new HttpServerHandler()
- 您不需要为每个通道创建此处理程序。 As it doesn't hold any state it may be shared across all pipelines. @Sharable
in netty. @Sharable
中搜索@Sharable
。 new LoggingHandler(LogLevel.INFO)
- you don't need this handler for high load tests as it logs a lot. new LoggingHandler(LogLevel.INFO)
- 你不需要这个处理程序来进行高负载测试,因为它记录了很多。 Make your own logging when necessary; buf.toString( utf8 )
- this is very wrong. buf.toString( utf8 )
- 这是非常错误的。 You convert income bytes to string. HttpServerCodec
. HttpServerCodec
解码。 So you do double work here; Unpooled.wrappedBuffer(CONTENT.getBytes())
- you wrap constant message on every request. Unpooled.wrappedBuffer(CONTENT.getBytes())
- 在每个请求上包装常量消息。 And thus - do unnecessary work on every request. retain()
, duplicate()
depending on how you'll do this; retain()
, duplicate()
具体取决于您将如何执行此操作; ctx.write(response)
- you may consider using ctx.write(response, ctx.voidPromise())
in order to allocate less; ctx.write(response)
- 您可以考虑使用ctx.write(response, ctx.voidPromise())
来分配更少的内容; This is not all. 这还不是全部。 However, fixing above issues would be a good start.
但是,解决上述问题将是一个良好的开端。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.