Netty websocket server压力测试

本文通过实验测试了Netty在网络连接、长连接保持、吞吐率及网络流量方面的性能表现,涉及不同连接数量下的时间消耗、内存占用及CPU利用率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

硬件配置:

压测客户端和服务器端在同一台pc上。Pc配置:

AMD A10-5800K APU with Radeon(tm) HD Graphics 3.80Ghz 四核

4G RAM

西数WDC WD10EZEX-60ZF5A0 ( 1 TB / 7200 转/分)  这个可以不写的

主要的测试目标分为:

1.       服务器端在一定时间内可接受客户端空闲连接的数量/峰值;

连接数

时间

1

180ms

1000

1150ms

2000

2207ms

6000

9000ms

每次建立tcp连接(包括web socket握手),平均需要180ms左右;

但是并不意味着 建立1000个连接需要180*1000ms,因为建立连接过程是异步的,详见压测客户端的代码。当建立较大量连接时(一万以内),所耗费的时间与连接数基本上是线性关系。

测试中,当测试6000连接数多于2次,在不重启jvm的情况下,测试程序客户端基本上就会报buffer空间不足的异常。

2.       服务器端同时保持空闲长连接的数量/峰值;

连接数

服务端java进程内存

服务端cpu利用率

0

358M

0%

6000

458M+

1%

10000

458M+

1%

服务器启动后,可以看到已使用内存为358M,客户端连接后为457M。它们之间的差值并不是保持所有连接 耗费的内存。因为建立连接过程中,在新生代中产生了很多垃圾内存。

 

标准的测试方法是:在开始连接之前,强制gc,这时看到是java进程真正占用的内存m1;在1w个连接建立之后,再次强制gc,用当前值m2减去上次gc后的内存值m1,才是保持连接实际占用的内存值,约为25M。

注意:频繁连接服务器建立1w个连接,即使全部断开,在客户端netstat –p依然可以看到这2w个端口在被占用着,未完全释放。这时就会出现异常 java.net.SocketException: No buffer space available (maximum connections reached?): connect 

3.       分别在单个连接和多个连接的情况下,统计服务器端netty网络层的吞吐率。

单连接 客户端发送PingWebSocketFrame:

时间表示客户端从发送第一个ping消息 开始计时,在收到最后一个pong消息后结束计时。

ping次数

时间

1k

160ms

3k

380ms

5k

550ms

1w

785ms

10w

2617ms

100w

24602ms

多连接:

连接数

每个连接ping次数

时间

吞吐率

1k

100

4280ms

23364

1k

500

10432ms

47929

1k

1k

18082ms

55303

1k

2k

36261ms

55155

2k

100

6900ms

28985

2k

500

19610ms

50994

2k

1000

33727ms

59299

3k

100

9752ms

30762

3k

500

31461ms

47678

3k

1000

56176ms 122491ms

压测无法进行(丢包,卡)

4.       测试网络流量

客户端向服务器端发送ClientRequest,payload为LoadTest对象,序列化为json字符串,大约800+个字符。可大致认为每条请求消息字符长度为800+。

连接数

每个连接请求次数

时间

平均每秒请求数

IO性能(每秒字符数)

1

1k

566ms

1766

 

1

5k

1099ms

4549

 

1

1w

1157ms

8643

 

1

10w

5601ms

17853

 

1k

100

11094ms

9013

 

2k

100

25959ms

7692

 

3k

100

40062ms

7500

 

 

 

 

 

 

<think>嗯,用户想在Spring Boot项目中集成Netty,以实现高性能的网络通信。首先,我得回忆一下Netty和Spring Boot整合的基本步骤。根据引用中的信息,特别是引用3提到需要在pom.xml中添加Netty的依赖,版本是4.1.94.Final。所以第一步应该是引入正确的依赖项。 然后,配置Netty服务器。通常需要创建ServerBootstrap,设置EventLoopGroup,指定通道类型,添加处理器等等。引用3和4都提到配置代码的问题,尤其是如何处理多个配置时的隔离性。用户可能需要一个Netty服务器的启动类,在Spring Boot启动时初始化Netty服务。 接下来是通道处理器,这部分需要自定义,比如继承ChannelInboundHandlerAdapter,处理消息接收和发送。引用2中的例子虽然主要讲的是WebSocket,但处理器的结构应该类似,需要覆盖channelRead等方法。 还有,如何让Netty服务随Spring Boot启动而启动?可能需要使用@PostConstruct注解,在Bean初始化后启动Netty服务器。同时,要注意关闭EventLoopGroup,防止资源泄漏,可以通过@PreDestroy来实现。 用户可能还关心如何与Spring的其他组件交互,比如在处理器中注入Spring管理的Bean。这里可能需要使用Spring的ApplicationContextAware,或者将处理器注册为Spring Bean,但要注意Netty的ChannelHandler通常是单例的,可能需要处理线程安全问题。 另外,引用4提到动态绑定和配置隔离的问题,如果用户需要多个Netty实例,可能需要不同的配置类来管理各自的ServerBootstrap和EventLoopGroup,确保它们互不干扰。这可能涉及到条件化配置或使用不同的配置属性。 最后,试部分,用户需要验证Netty是否成功启动,可以像引用2那样添加一个REST接口返回状态,或者通过日志查看端口监听情况。同时,编写客户端试连接和消息收发是否正常。 总结步骤:添加依赖、配置服务器类、定义处理器、整合生命周期、处理Bean注入、试。确保每个步骤都符合最佳实践,并参考了提供的引用内容,比如依赖版本和配置代码的结构。</think>### 在 Spring Boot 中集成 Netty 的步骤 #### 1. 添加 Netty 依赖 在 `pom.xml` 中引入 Netty 官方库(版本需与 Spring Boot 兼容): ```xml <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.94.Final</version> </dependency> ``` 此版本解决了原生 NIO 长轮询 CPU 占用过高的问题,并优化了 `ByteBuffer` 功能[^3]。 --- #### 2. 配置 Netty 服务器 创建 `NettyServer` 类,管理 Netty 服务生命周期: ```java @Component public class NettyServer { private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; @Value("${netty.port:8080}") private int port; @PostConstruct public void start() throws InterruptedException { bossGroup = new NioEventLoopGroup(1); workerGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new NettyServerHandler()); } }); bootstrap.bind(port).sync(); } @PreDestroy public void shutdown() { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } ``` - **关键点**: - 使用 `@PostConstruct` 在 Spring Boot 启动后自动初始化 Netty - 通过 `@PreDestroy` 确保资源释放 - 支持多端口隔离配置(需扩展为多实例模式)[^4] --- #### 3. 实现自定义处理器 定义 `NettyServerHandler` 处理网络事件: ```java public class NettyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 处理业务逻辑(如解码、协议解析等) ByteBuf buf = (ByteBuf) msg; String received = buf.toString(CharsetUtil.UTF_8); System.out.println("Received: " + received); ctx.writeAndFlush(Unpooled.copiedBuffer("OK", CharsetUtil.UTF_8)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } ``` --- #### 4. 整合 Spring 组件 若需在处理器中使用 Spring Bean(如数据库操作),需通过 `ApplicationContext` 注入: ```java @Component public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext ctx) { context = ctx; } public static <T> T getBean(Class<T> clazz) { return context.getBean(clazz); } } ``` 在处理器中调用:`SpringContextHolder.getBean(MyService.class)`。 --- #### 5. 验证服务状态 添加 REST 接口验证 Netty 是否运行: ```java @RestController @RequestMapping("/api") public class StatusController { @GetMapping("/status") public String checkStatus() { return "Netty server is running"; } } ``` 通过 `curl http://localhost:8080/api/status` 确认服务状态[^2]。 --- ### 性能优化建议 1. **线程模型**:根据业务负载调整 `EventLoopGroup` 线程数 2. **内存管理**:使用 `ByteBuf` 池化减少 GC 力 3. **协议设计**:采用 Protobuf 或自定义二进制协议提升传输效率
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值