【Netty源码解读和权威指南】第41篇:Netty开发HTTP服务——打造轻量级Web服务器
·
上一篇【第40篇】Netty内存管理深度解析——PoolChunk/PoolArena源码全剖析
下一篇【第42篇】Netty开发HTTP客户端——高并发请求轻松搞定
一、HTTP协议处理Pipeline
// 标准HTTP Pipeline
pipeline.addLast(new HttpServerCodec()); // HTTP编解码
pipeline.addLast(new HttpObjectAggregator(65536)); // 聚合请求/响应
pipeline.addLast(new HttpServerExpectContinueHandler());
pipeline.addLast(new HttpServerHandler()); // 业务处理
二、完整的HTTP服务器
public class NettyHttpServer {
public static void main(String[] args) throws Exception {
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(boss, worker).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new HttpObjectAggregator(65536));
ch.pipeline().addLast(new SimpleRouter());
}
});
b.bind(8080).sync().channel().closeFuture().sync();
} finally { boss.shutdownGracefully(); worker.shutdownGracefully(); }
}
}
class SimpleRouter extends SimpleChannelInboundHandler<FullHttpRequest> {
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) {
String uri = req.uri();
String method = req.method().name();
// 路由分发
String result;
if ("/api/user".equals(uri) && "GET".equals(method)) {
result = "{\"name\":\"Alice\",\"age\":25}";
sendJson(ctx, result);
} else if ("/api/order".equals(uri) && "POST".equals(method)) {
String body = req.content().toString(CharsetUtil.UTF_8);
result = "{\"status\":\"created\",\"body\":\"" + body + "\"}";
sendJson(ctx, result);
} else if ("/".equals(uri)) {
sendHtml(ctx, "<h1>Hello Netty HTTP Server!</h1>");
} else {
sendError(ctx, NOT_FOUND, "Not Found");
}
}
private void sendJson(ChannelHandlerContext ctx, String json) {
FullHttpResponse resp = new DefaultFullHttpResponse(HTTP_1_1, OK,
ctx.alloc().buffer().writeBytes(json.getBytes()));
resp.headers().set(CONTENT_TYPE, "application/json");
resp.headers().set(CONTENT_LENGTH, resp.content().readableBytes());
ctx.writeAndFlush(resp);
}
}
三、Chunked分块传输
大文件使用Chunked编码,避免内存中缓存整个文件:
public class FileSender extends SimpleChannelInboundHandler<FullHttpRequest> {
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) {
try {
RandomAccessFile file = new RandomAccessFile("largefile.mp4", "r");
HttpResponse resp = new DefaultHttpResponse(HTTP_1_1, OK);
resp.headers().set(CONTENT_TYPE, "video/mp4");
ctx.write(resp);
// Chunked分块写入
ctx.write(new ChunkedFile(file, 0, file.length(), 8192));
ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
} catch (Exception e) { ctx.close(); }
}
}
四、性能对比
| 服务器 | 静态QPS | 动态QPS |
|---|---|---|
| Netty HTTP | 150,000 | 80,000 |
| Tomcat | 30,000 | 25,000 |
| Undertow | 120,000 | 65,000 |
五、总结
| 组件 | 功能 |
|---|---|
HttpServerCodec |
HTTP请求/响应编解码 |
HttpObjectAggregator |
聚合分块请求 |
FullHttpRequest/Response |
完整HTTP消息 |
ChunkedFile |
大文件分块传输 |
上一篇【第40篇】Netty内存管理深度解析——PoolChunk/PoolArena源码全剖析
下一篇【第42篇】Netty开发HTTP客户端——高并发请求轻松搞定
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)