Netty JVM内本地传输使用示例及基于其实现反向代理的咨询
Netty 本地传输反向代理实现方案
Netty 本地传输的核心是通过LocalAddress作为唯一标识,使用JVM内部内存交换数据,跳过操作系统网络栈,性能远高于loopback网卡的环回请求,完全适配你描述的同JVM进程内请求转发场景。
核心架构对应关系
- 对外Web服务端:基于NIO传输监听公网端口,接收用户的HTTP请求
- 本地传输服务端:绑定自定义
LocalAddress,接收Web服务端转发的内部请求 - 本地传输客户端:连接到上述
LocalAddress,拿到请求后向外部目标主机发起调用,收到响应后原路回传给Web服务端
实现示例
1. 基础依赖(Maven)
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.97.Final</version> </dependency>
2. 本地传输服务端启动逻辑
// 可复用Web服务端的EventLoop,减少线程开销 EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); // 自定义本地地址标识,同JVM内唯一即可 LocalAddress localAddress = new LocalAddress("internal-proxy"); ServerBootstrap localServer = new ServerBootstrap() .group(eventLoopGroup) // 核心:指定本地传输服务端Channel实现 .channel(LocalServerChannel.class) .childHandler(new ChannelInitializer<LocalChannel>() { @Override protected void initChannel(LocalChannel ch) { ChannelPipeline p = ch.pipeline(); // 按需添加HTTP编解码器、聚合器 p.addLast(new HttpClientCodec()); p.addLast(new HttpObjectAggregator(1024 * 1024)); // 自定义处理器:把本地传输收到的响应回写给公网用户的Channel p.addLast(new LocalRespForwardHandler()); } }); // 绑定本地地址 localServer.bind(localAddress).syncUninterruptibly();
3. 公网Web服务端请求转发逻辑
// 公网请求处理器的channelRead方法里,拿到完整HTTP请求后转发 @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) { // 提前创建好本地传输客户端的Channel池,避免每次请求新建连接 Channel localClientChannel = getLocalClientChannelFromPool(); // 保留ByteBuf引用,直接转发避免拷贝 localClientChannel.writeAndFlush(req.retain()).addListener((ChannelFutureListener) future -> { if (!future.isSuccess()) { ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR)); } }); }
4. 本地传输客户端启动逻辑
Bootstrap localClient = new Bootstrap() .group(eventLoopGroup) // 核心:指定本地传输客户端Channel实现 .channel(LocalChannel.class) .handler(new ChannelInitializer<LocalChannel>() { @Override protected void initChannel(LocalChannel ch) { ChannelPipeline p = ch.pipeline(); p.addLast(new HttpClientCodec()); p.addLast(new HttpObjectAggregator(1024 * 1024)); // 自定义处理器:拿到本地传输的请求后,发往外部目标主机 p.addLast(new ExternalReqForwardHandler()); } }); // 连接到之前绑定的本地地址 localClient.connect(localAddress).syncUninterruptibly();
注意事项
LocalAddress不需要对应实际端口,只要保证同一JVM内的服务端和客户端使用相同的字符串标识即可- 转发过程中注意ByteBuf的引用计数,调用
retain()后直接传递,避免内存拷贝和泄漏 - 本地传输不支持TCP相关的参数配置,比如
SO_KEEPALIVE、TCP_NODELAY等,启动时不要添加不支持的选项 - 如果需要处理并发请求,建议为本地传输连接实现Channel池,减少连接创建开销
内容的提问来源于stack exchange,提问作者jascadev
相关产品推荐
相关产品推荐

