背景
刚接触到这个项目的时候,只负责其中很简单的一个模块,因为各种原因,开始负责这个项目,刚开始只是正常的业务开发,而且原来是提供给自己内部的系统调用,没有什么问题,直到该项目提供的接口针对到各个部门,开始出现性能上的问题。
接口优化
该项目提供给外部一个查询的接口,业务量不大的时候体现不出来,数据量上去之后,访问速度变慢,记录一下优化的方向。
1.修改校验
rpc的入参校验,为了方便校验简化代码,使用Hibernate-Validator的参数校验,很方便,但是在一定程度上会影响接口的性能,不适合使用在对响应速度要求高的场景,直接替换为最原始的判断方式。
项目不方便用来展示,写了个小demo
@Data
public class Member {
@NotBlank
private String name;
@NotNull
private Integer age;
}
@Test
public void test() {
Member member = new Member();
long start = System.currentTimeMillis();
Set<ConstraintViolation<Member>> violationSet = validator.validate(member);
for (ConstraintViolation<Member> model : violationSet) {
System.out.println(model.getMessage());
}
long end = System.currentTimeMillis();
System.out.println("校验用时:"+ (end - start) + "ms");
}
@Test
public void test1() {
Member member = new Member();
long start = System.currentTimeMillis();
if (StringUtils.isBlank(member.getName())) {
System.out.println("姓名不能为空");
}
if (member.getAge() == null) {
System.out.println("年龄不能为空");
}
long end = System.currentTimeMillis();
System.out.println("校验用时:"+ (end - start) + "ms");
}
输出结果均为:
姓名不能为空 年龄不能为空
test用时:100 ms
test 1用时: 1 ms
2.优化逻辑
梳理业务逻辑,优化细节,整合逻辑。
接口内部需要调用两次外部rpc接口改为一次,减少查询本库的次数,将表中变化不太大的信息批量放到redis缓存中,redis每天更新一次,更新期间的查询走数据库,细节省略.....
3.优化查询
优化查询速度,增加mysql索引,提高查询速度,本地模拟新增50多万数据,
未索引前查询时间:998 ms;加索引之后查询时间:31 ms
1577107221122.png
未加索引查询扫描全表,扫描行数为51万,加索引之后扫描行数降为23。效果明显。
4.优化赋值
数据库查询出来的结果需要进行修改和赋值,使用了spring封装的BeanUtils的copyProperties方法,该静态方法使用的是反射机制将对象赋值,修改方法为直接使用最简单的get,set方式,修改sql的返回对象。
Member member = new Member();
member.setName("张三");
member.setAge(18);
Person person = new Person();
//修改前
BeanUtils.copyProperties(member, person);
//修改后
person.setName(member.getName());
person.setAge(member.getAge());
5.采坑
有一步需要新增接口的访问记录,初步想到的是将新增的操作改成异步执行,但是测试在压测的时候线程池爆掉了,最终改了回来,之后了解了一下线程池的拒绝策略。
还有两个方案:1.将新增的操作交给消息中间件MQ来执行。2.将新增的数据先收集起来,定时刷到库中。
6.结果
该接口未优化前,调用时间2 s左右,qps只有7(测试机性能不高),压测的时候有时还会降到3....优化之后调用时间降到了100 ms内,qps达到了50之后,由于网络带宽受限上不去了,速度明显上升了很高。
总结
优化接口的思路,1.优化业务逻辑,2.优化费时的校验,3.优化数据库的查询,4.把和主流程影响不大的逻辑提取出来,5.坚决避免for循环连接数据库。
还有很多方面可以优化的地方,以后再补充~
网友评论