美文网首页
接口优化

接口优化

作者: hqwer | 来源:发表于2019-12-24 21:17 被阅读0次

    背景

    刚接触到这个项目的时候,只负责其中很简单的一个模块,因为各种原因,开始负责这个项目,刚开始只是正常的业务开发,而且原来是提供给自己内部的系统调用,没有什么问题,直到该项目提供的接口针对到各个部门,开始出现性能上的问题。

    接口优化

    该项目提供给外部一个查询的接口,业务量不大的时候体现不出来,数据量上去之后,访问速度变慢,记录一下优化的方向。

    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

    1577107169112.png
    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循环连接数据库。
    还有很多方面可以优化的地方,以后再补充~

    相关文章

      网友评论

          本文标题:接口优化

          本文链接:https://www.haomeiwen.com/subject/vxstoctx.html