性能调优单接口性能调优预备阶段
Posted sysu_lluozh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性能调优单接口性能调优预备阶段相关的知识,希望对你有一定的参考价值。
一、现状
在性能测试一开始就针对全接口全场景进行性能压测并调优,如果再加上对业务代码不熟悉,基本上就是熟悉的尴尬场景:
- 阶梯递增并发线程数获得服务性能拐点
- 调整服务端数据库连接池配置
- 调整JVM中新生代老年代等配置
- 优化监控获得的慢sql语句
- 利用工具分析线程堆栈信息
不了解业务逻辑,不了解具体代码实现,基本上这些招数使用后对于性能优化就毫无头绪且无能为力了
接下来看看调优从开始准备到调优完成整个流程中更为有针对性的方式,需要在调优前更加充分的准备,更加深入的分析业务实现代码,且提前预估性能风险点,有利于接下来的性能优化
二、 功能模块
需要熟悉该接口实现的业务功能模块,入参出参以及代表的业务逻辑
三、业务代码
3.1 目的
- 风险提前暴露
- 接口性能大概评估
- 测试场景的设计
3.2 聚焦点
- sql或外部接口重复调用
同一个信息在不同的地方重复查询 - sql索引命中
索引的规则优化 - 设计缺陷风险
redis穿透
循环嵌套是否合理for for循环
事务
3.3 统计项
主要是为了统计sql及外部调用的类型和次数,方便大致评估接口性能
- 统计不同类型sql的次数(读、写)
- 统计调用外部接口的次数
3.4 日志信息
对象定义中自定义toString()方法,避免序列化,避免直接使用toJsonString(占用30%+内存)
四、中间件
4.1 redis
- 需注意点
- 缓存命中率
- redis失效时间+随机事件
如果业务可能存在定期刷数据、预热等 - 回源并发度的控制
某一个key失效时多个线程并发请求导致回源并发压力大 - hot key的风险
某个hot key在一台redis中,请求都访问该redis,导致redis负载不均匀 - 大key的风险
- 案例代码
@Override
public User getByUidFromCache(String userId) {
if (StringUtils.isBlank(userId)) {
return null;
}
User user = userRedisService.getByUserUid(userId);
if (user != null) {
//表示该用户数据属于活跃数据,延长在redis中的有效时间
return user;
}
user = getByUidFromDB(userId);
if (user == null) {
return null;
}
LOGGER.info("将用户信息放到缓存中,用户信息为:{}", user);
//用户信息放到redis缓存中
userRedisService.put(user);
return user;
}
4.2 调用外部接口
- 从同一个外部服务不同接口查询同类信息
优化对策:外部接口提供一个粗颗粒度的接口 - 外部接口返回多个无用字段
优化对策:定制接口返回必须字段(返回数据量比较大时明显)
4.3 mysql连接配置
-
基本原则
连接数够用即可 -
连接数性能消耗
连接数大的弊端维护自身线程状态检测消耗大(SELECT 1)
sql执行时间长并发小 sql执行时间短并发大
五、第一瓶颈点
以上是在性能压测前需要关注分析的点,获得接口性能评估的大致情况后需要开始真正实施性能压测
接下来各个维度逐步找到当前的性能第一瓶颈点并优化之
5.1 压测线程
- 单个线程压测
记录此时的cpu占用、内存、磁盘、网络,不过重点关注cpu的占用信息
- 倍增并发线程
查看此时cpu是否等比增加
5.2 磁盘数据
主要是日志写入,日志落盘、传输
以上是关于性能调优单接口性能调优预备阶段的主要内容,如果未能解决你的问题,请参考以下文章