基于 Spring Boot 3.x + Netty 4.1.x 的 服务端、客户端、WebFlux、WebSocket 四合一实践
含 完整源码、生命周期、线程模型、自动配置 解析
目录
- 背景:为什么要在 Spring 里用 Netty
- 整体架构
- 场景一:内嵌 Netty 作为 Web 容器
- 场景二:自定义 TCP/UDP 服务器
- 场景三:WebSocket 长连接
- Spring Boot 自动装配源码走读
- 生命周期与线程模型
- 最佳实践与性能调优
- 常见问题 FAQ
- 总结
背景
- Tomcat/Jetty 是阻塞式 Servlet 容器,高并发场景下线程消耗大。
- Netty 采用 NIO + 事件驱动,单线程可支撑 万级连接。
- Spring Boot 3.x 官方支持 WebFlux 与 Reactor Netty,整合更丝滑。
整体架构
场景一:内嵌 Netty 作为 Web 容器(WebFlux)
1. 引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
spring-boot-starter-webflux默认使用 Reactor Netty(Netty 的响应式封装)。
2. 自定义配置(可选)
@Configuration
public class NettyWebFluxConfig implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {@Overridepublic void customize(NettyReactiveWebServerFactory factory) {factory.addServerCustomizers(httpServer ->httpServer.port(9000).option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.TCP_NODELAY, true));}
}
3. 路由示例
@SpringBootApplication
public class WebFluxApplication {public static void main(String[] args) {SpringApplication.run(WebfluxApplication.class, args);}@Beanpublic RouterFunction<ServerResponse> route() {return RouterFunctions.route(GET("/hello"), req -> ServerResponse.ok().bodyValue("Hello Netty"));}
}
访问 http://localhost:9000/hello 即可返回 Hello Netty。
场景二:自定义 TCP/UDP 服务器
1. Maven 依赖
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.110.Final</version>
</dependency>
2. 启动器(跟随 Spring 生命周期)
@Component
public class TcpServer implements SmartLifecycle {private final EventLoopGroup boss = new NioEventLoopGroup(1);private final EventLoopGroup worker = new NioEventLoopGroup(0);private Channel channel;@Overridepublic void start() {try {ServerBootstrap bootstrap = new ServerBootstrap().group(boss, worker).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ChannelPipeline p = ch.pipeline();p.addLast(new StringDecoder());p.addLast(new StringEncoder());p.addLast(new SimpleChannelInboundHandler<String>() {@Autowiredprivate EchoService service; // Spring 注入@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {ctx.writeAndFlush(service.echo(msg));}});}});channel = bootstrap.bind(8888).sync().channel();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}@Overridepublic void stop() {if (channel != null) channel.close();boss.shutdownGracefully();worker.shutdownGracefully();}@Overridepublic boolean isRunning() {return channel != null && channel.isActive();}
}
3. 业务 Service
@Service
public class EchoService {public String echo(String msg) {return "Echo: " + msg;}
}
场景三:WebSocket 长连接
@Component
public class WebSocketServer implements SmartLifecycle {@Overridepublic void start() throws Exception {ServerBootstrap bootstrap = new ServerBootstrap().group(new NioEventLoopGroup(1), new NioEventLoopGroup()).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new HttpServerCodec()).addLast(new HttpObjectAggregator(65536)).addLast(new WebSocketServerProtocolHandler("/ws")).addLast(new SimpleChannelInboundHandler<TextWebSocketFrame>() {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {ctx.writeAndFlush(new TextWebSocketFrame("Received: " + frame.text()));}});}});bootstrap.bind(9999).sync();}
}
客户端连接 ws://localhost:9999/ws 即可实时通信。
Spring Boot 自动装配源码走读
1. 入口:ReactorNettyAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(HttpServer.class)
@EnableConfigurationProperties(ServerProperties.class)
public class ReactorNettyAutoConfiguration {@Beanpublic NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {return new NettyReactiveWebServerFactory();}
}
2. 工厂创建 ServerBootstrap
public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory {@Overridepublic WebServer getWebServer(HttpHandler httpHandler) {return new NettyWebServer(HttpServer.create().port(getPort()).handle(new ReactorHttpHandlerAdapter(httpHandler)));}
}
生命周期与线程模型
| 阶段 | 线程 | 说明 |
|---|---|---|
| 启动 | 主线程 | Spring Boot SmartLifecycle |
| Accept | Boss EventLoop | 单线程处理连接事件 |
| I/O | Worker EventLoop | 多线程处理读写 |
| 业务 | Worker 或自定义线程池 | 耗时任务外移 |
最佳实践
| 建议 | 配置 |
|---|---|
| 线程数 | Boss=1,Worker=CPU*2 |
| ChannelOption | SO_BACKLOG=1024, TCP_NODELAY=true |
| ChannelHandler | 使用 @Sharable 保证单例 |
| 内存 | ByteBuf.release() 避免泄漏 |
常见问题 FAQ
| 问题 | 解决 |
|---|---|
| 端口冲突 | server.port 与 netty.port 分离 |
| Handler 非 Spring Bean | 使用 @Component + @Autowired |
| 优雅关闭 | EventLoopGroup.shutdownGracefully() |
总结
- Spring Boot + Netty = 阻塞逻辑 与 非阻塞 I/O 的完美结合
- WebFlux 内置,自定义 TCP/UDP/WebSocket 三行代码即可
- 掌握 生命周期、线程模型、ChannelOption,即可构建 万级并发 的 Spring 应用!
可以进扣扣裙(651706395),互相交流!
