系统性能指标、压测、性能优化思路

本文介绍如何使用压力测试工具Apache JMeter对系统进行压测,分析压测结果,并通过调整Nginx配置、优化数据库查询及JVM设置等方式提高系统性能。
压测

压力测试考察的是当前软硬件环境下系统所能承受的最大负荷并帮助找出系统的瓶颈所在,压测都是为了系统在线上的处理能力和稳定性维持在一定的范围内,做到心中有数。

使用压力测试,我们有希望找到很多种用其他测试方法更能发现的错误,比如内存泄露、并发与同步等。

有效的压力测试系统将应用以下关键条件:重复、并发、量级、随机变化。

系统的性能指标
  • 响应时间(Response Time:RT):响应时间指的是用户冲客户端发起一个请求开始,到客户端接收到从服务端返回的响应结束,整个过程所耗费的时间。
  • HPS(Hits Per Second):每秒点击次数,单位次/秒。
  • TPS(Transaction Per Second):系统每秒处理的事务数,单位是笔/秒,这里的事务不是具体指数据库事务,而是一个业务功能的全流程,比如下单功能的全业务流程称为一个事务,而TPS表示每秒能下单的数量。
  • QPS(Query Per Second):系统每秒处理的查询次数。一般用TPS来衡量整个业务流程,用QPS来衡量接口查询次数,用HPS来表示对服务器的单击请求。这三者用吞吐量来解释。
  • 最大响应时间:指的是用户发出请求开始,到收到服务器响应所耗费的最大时间。
  • 最小响应时间:指的是用户发出请求开始,到收到服务器响应所耗费的最小时间。
  • 90%响应时间:是指对用户的请求响应时间进行排序,第90%的请求的响应时间,比如100个请求的响应时间进行排序,那么第90个请求的响应时间就是90%响应时间。
  • 从外部看,系统性能主要看三个指标:
    )吞吐量:TPS、QPS。
    )响应时间。
    )错误率:一批请求中,响应结果出错的请求所占的比例。
性能优化实战

影响性能的问题考虑:
数据库、应用程序、中间件、网络、操作系统、业务代码等。
首先考虑是CPU密集型应用还是IO密集型应用,CPU密集型可能要加CPU核心,IO密集型可以换固态硬盘,或者使用缓存工具,比如Nginx。

该性能优化使用的是尚硅谷谷粒商城2020的首页接口来进行压测并优化。因为java程序。nginx啥的全部都是在同一台机器上,所以结果不是很标准,主要提供一个思路。
目前调用链路是这样的:
客户端->nginx->网关->首页

使用工具

  • Apache Jmeter 压测工具
  • JVisualvm 系统运行信息,比如线程、JVM的信息。

初始压测:

压测内容压测线程数吞吐量90%响应时间99%响应时间
Nginx使用2000个线程压,每个线程压十次10次39851793022
Gateway使用2000个线程压,每个线程压十次10次992513
首页一级菜单渲染使用1500个线程压,每个线程压十次10次20989799519
三级分类获取使用300个线程压,每个线程压十次10次413490137730
首页全量数据获取(一级菜单加各种静态文件js/css/图片等)使用50个线程压,每个线程压2次2424202569
全链路(包括静态资源)使用50个线程压,每个线程压2次1.26796175675

尝试优化系nginx,比如集群,这里没有多余的机器,就不集群了,那就尝试优化增加nginx的工作进程,原本是1个工作进程,因为虚拟机的cpu核心数是2,所以就增加一个工作进程。
在这里插入图片描述

压测内容压测线程数吞吐量90%响应时间99%响应时间
Nginx(增加一个工作进程后)使用2000个线程压,每个线程压十次10次5011591118

得到了一些优化,吞吐量上去了,90%和99%的响应时间也变小了,如果cpu核心数更多,可以创建更多的工作进程,或者能够进行集群,那么优化效果更佳。

优化一级菜单渲染:

优化点:开启thymeleaf的缓存功能。把日志等级调到warn。数据库对parent_cid建立索引,JVM的堆内存调大。

因为当初为了能启动多个服务,把每个服务的JVM堆内存设置到了100m。导致频繁的触发yonggc和fullgc。
在这里插入图片描述
可以看到触发了759次fullgc,耗费了51.186秒。80次younggc,耗费了250毫秒,现在把内存调大,避免频繁的fullgc。

设置堆大小为1024m,新生代的大小为512m,因为这种业务大多数的对象都是短命的,请求结束后就死了。所以把新生代的大小稍微调大点。
参数:-Xms1024m -Xmx1024m -Xmn512m

在这里插入图片描述

压测内容压测线程数吞吐量90%响应时间99%响应时间
首页一级菜单渲染使用1500个线程压,每个线程压十次10次17418891055

相比原来的209吞吐量,增大了近9倍的吞吐量。并且该增长的瓶颈就在JVM的内存上,开启缓存、加表索引、关日志后的吞吐量达400,加上JVM内存后,大1741。

在这里插入图片描述
可见仅仅发生了两次fullgc,耗费51毫秒。

三级分类获取渲染

上面的开启thymeleaf的缓存功能。把日志等级调到warn。数据库对parent_cid建立索引,JVM的堆内存调大。在这里同样适用,并且我的业务代码问题不大,一开始就没有跟尚硅谷的老师那样循环访问数据库。所以我的业务代码无需更改。

因为查询三级分类,查询的数据量比较大,所以加索引的功效会明显于上面的一级分类。

在这里插入图片描述
在这里插入图片描述
吞吐量从41增长到297。并且只发送2次fullgc。

首页全量数据获取(一级菜单加各种静态文件js/css/图片等)

这里的优化手段是把静态资源文件放到nginx上转发,程序的tomcat服务器只处理动态请求。实现动静分离,因为tomcat会分出线程来对静态资源文件的处理。所以要实现动静分离。
在这里插入图片描述
把静态资源文件放上nginx后,直接访问商城访问不到静态文件,所以这里测试的是全链路,包括下载静态文件的吞吐量。

在这里插入图片描述
全链路不下载文件,的吞吐量达99.

其他优化思路

数据上缓存,比如redis,性能会得到巨大的提升。。集群。

<think>嗯,用户这次聚焦在开源IM系统的性能上,看来他正在评估某个IM系统的承载能力或者准备做扩容规划。结合之前的对话,他应该是个技术负责人或架构师,对分布式系统有基本认知但需要具体实践指导。用户特意提到站内引用,其中几个关键点值得注意:引用1强调全链路的价值,引用2提到JMeter工具,引用3/5提到Go语言实现的IM架构特性。这些正好构成方法论的核心——既要懂工具操作,也要理解IM系统特殊构造。先从类型入手比较合理。基准试是基础,用户需要先确认单接口性能天花板;稳定性试对IM尤其重要,毕竟聊天服务崩溃会直接影响用户体验。全链路部分虽然复杂,但引用1里阿里案例已经证明必要性,得重点说明。工具选型上,JMeter是首选(呼应引用2),但要注意WebSocket协议的特殊性。用户可能不知道JMeter需要安装额外插件才能支持ws,这点必须强调。对于全链路场景,Tcpcopy这类流量复制工具更接近真实环境,比纯脚本模拟有效。点设计要抓住IM核心瓶颈:登录和消息同步力最大。引用3提到Go语言IM的消息分发架构,时需特别关注这部分模块的CPU和内存表现。用户若用类似Mattermost的Go方案,还要考虑集群下的分片性能。实施步骤需要区分预热阶段——很多人会忽略这点导致试结果失真。引用1提到的"线上单机引流"方法,实际上就是灰度放量思路,可以转化为分阶段增加线程数的实操建议。指标监控环节,用户可能对延迟指标理解有偏差。普通用户能感知的是消息发送到接收延迟,但内部要拆分成网络传输、队列等待、持久化等分段耗时。引用5提到的HTTP/WebSocket双接入方式,两种路径的延迟特征也不同。最后的风险控制,用户最怕垮生产环境。引用4的弹性调度方案值得借鉴,比如在期间动态扩容。但更保险的做法是像引用1说的做流量标记,让试流量走影子库。用户可能还想知道:开源方案能否做分布式?建议补充Locust工具;报告怎么分析?可以给个响应时间百分位数的统计范例。不过当前回答已覆盖主要痛点,进阶问题留到后续展开更合适。</think> 对开源即时通讯系统进行性能需要**系统性方法**和**专业工具**,以下是完整实践指南(含工具推荐与实施步骤): --- ### 一、核心目标 1. **关键性能指标**(需监控): - 消息延迟:$ \text{Latency} = T_{\text{receive}} - T_{\text{send}} $ - 吞吐量:QPS(消息数/秒) - 系统稳定性:CPU/RAM/网络波动率 - 最大并发连接数 - 断线重连成功率 --- ### 二、工具选择(推荐组合方案) | 工具类型 | 推荐工具 | 适用场景 | |----------------|------------------------------|-----------------------------------| | 协议级 | **JMeter**(需WebSocket插件)[^2] | 模拟登录、消息收发基础场景 | | 全链路 | **Tcpcopy** + **GoReplay** | 真实流量复制(生产环境影子) | | 集群监控 | **Grafana** + **Prometheus** | 实时资源消耗可视化 | | WebSocket专 | **WebSocketBench** | 长连接并发 | > ✨ **工具配置示例(JMeterWebSocket)**: > ```xml > <WebSocketSampler> > <server>im.example.com:443</server> > <path>/chat</path> > <payload>{"type":"text","content":"test"}</payload> > <threads>5000</threads> <!-- 并发数 --> > </WebSocketSampler> > ``` --- ### 三、全链路实施流程[^1] 1. **环境隔离** 创建**影子数据库**和**消息队列**,与生产环境物理隔离 2. **流量染色** 通过请求头植入试标记(如:`X-Test: pressure`) 3. **流量复制** 使用Tcpcopy将生产流量转发至试集群: ```bash tcpcopy -x 80-试机IP:80 -s 生产机IP -c 192.168.x.x -d ``` 4. **执行** 按梯度增加负载(建议阶梯式): ```mermaid graph LR A[10% 正常流量] --> B[50%峰值流量] B --> C[100%峰值] C --> D[120%极限力] ``` 5. **故障注入** 模拟网络分区/节点宕机: ```bash iptables -A INPUT -p tcp --dport 8080 -j DROP # 阻塞IM端口 ``` --- ### 四、重点场景设计 | 场景 | 检目标 | 方法 | |-----------------------|----------------------------|----------------------------------------------------------------------| | 登录风暴 | 认证服务抗能力 | 短时发起10万+登录请求 | | 群聊广播 | 消息扩散效率 | 5000人在线时发群消息(监控各节点接收延迟差) | | 离线消息同步 | 存储系统I/O瓶颈 | 断连24小时后重连,拉取500条历史消息 | | 心跳包力 | 长连接维护成本 | 10万连接下每30秒发PING(观察服务端CPU) | | 消息洪峰 | 流控机制有效性 | 1秒内向单个用户推送1000条消息 | --- ### 五、性能优化方向(根据结果) 1. **架构层** - 消息分发模块改用Golang协程池(提升并发处理能力)[^3] - 热数据迁移至Redis Cluster(降低DB读力) ```go // Go消息分发伪代码 func handleMessage(msg Message) { go pool.Submit(func() { routeMsg(msg) // 异步路由 }) } ``` 2. **协议层** 启用ProtoBuf缩(体积减小60%): ``` 原始JSON: {"from":"user1","to":"group5","content":"hello"} ProtoBuf: 0A 05 75 73 65 72 31 12 05 67 72 6F 75 70 35 1A 05 68 65 6C 6C 6F ``` 3. **部署层** 消息服务与业务服务分离(避免HTTP接口阻塞WebSocket) --- ### 六、报告关键指标示例 | 力级别 | 平均延迟 | 吞吐量(msg/s) | CPU使用率 | 异常率 | |----------------|----------|---------------|-----------|--------| | 正常负载(1万) | 82ms | 9,200 | 43% | 0% | | 峰值力(5万) | 217ms | 21,800 | 91% | 0.2% | | 极限力(10万) | 482ms | 28,400 | 98% | 2.1% | > 📌 **结论建议**:当用户量突破8万时需水平扩展消息分发节点 --- **相关实践案例**:某电商IM系统通过全链路发现MySQL写入瓶颈,改用分库分表后,消息延迟从350ms降至95ms[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值