美文网首页
关于一个简单接口的高并发测试与优化记录

关于一个简单接口的高并发测试与优化记录

作者: 草编椅 | 来源:发表于2020-06-30 17:39 被阅读0次

    目的

    通过测试,了解高并发需求的各处细节,寻找制约因素;为软件框架 和 硬件架构提供优化参考。

    前述

    • 优化前,目标接口在测试环境的qps为160左右
    • 目标接口的内部逻辑
      • 处理前1:开始计时
      • 处理前2:较验IP白名单[rpc]
      • 处理:
        • 查询数据库并缓存
      • 处理后1:结束计时;提交性能报告[rpc];提交输入输出日志[rpc]
        • 日志通过RPC,最终写入数据库
    • 目标接口特征:
      • 内部处理简单
      • 可监测点比较清晰

    开始测试

    • 使用一个nio或aio的通道框架测试helloworld

      • 使用本机测试,qps约为:450万(我的电脑4c 16g)
        • 如果server端的服务线程,加个System.out.println;qps约为:20万(缩了20多倍)
    • 使用solon.boot.jlhttp,测试helloworld(单机,单实例)

      • 使用本机测试,qps 约为:5万(我的电脑4c 16g)
      • 使用域局网测试(192.168.8.118),qps约为:2万(2c 16g)
    • 测试目标接口 getAppByID (服务端为单机单实例;测试端为另一台机,走的是内网)

      • 服务端测试机情况
        • 上面有8个java服务;docker服务(memcached,redis,mysql);
      • 初始测试
        • qps约为:160
      • 去掉三个触发器(即前后处理,相当于Spring的过滤器)
        • -不用缓存,qps约为:600
        • +memcached,qps约为:1万(memcached 在本机,应该有优势;否则可能差些)
        • +二级缓存,qps约为:1.5万
        • 从DB角度思考,如果涉及写。。。qps只能靠DB的硬件提升了(量大时,还要靠分库分表)
      • 加上触发器 + 二级缓存
        • +记性能,qps约为:750
        • +记性能 +记日志,qps约为;240(异步http提交日志;可能存储在本机会有较大负影响;sev->http->db->磁盘
        • +记性能 +记日志 +白名单较验,qps约为:160
        • +白名单较验,qps约为:900

    优化一

    • 将okhttp异步,改为线程池加同步(okhttp自带的异步,因为有融断机制性能差些)
      • +记性能 +记日志,qps约为;320(异步http提交日志;明明是异步了,为什么还这么低?因为还有IO频次)
      • +记性能 +记日志 +白名单较验,qps约为:200

    优化二

    • 为白名单增加10s本地缓存
      • +白名单较验,qps约为:1.1万(::从900提到1.1万了;不同时间测值会有波动)
      • +记性能 +记日志 +白名单较验,qps约为:320

    优化三

    • 性能记录,改为本地收集 + 5秒间隔提交(可称为缓冲模式)

      • +记性能 +白名单较验,qps约为:6000(应该还有优化空间)
      • +记性能 +记日志 +白名单较验,qps约为:800
    • 日志级别动态可控,可在非必要时控制日志提交量(对于业务系统,这个控制是非常之必要)

      //日志级别动态切换控制
      WaterClient.Config.subscribe("sponge", (set)->{
          int level = set.get("rock_log_level").getInt();
          WaterLogger.setLevel(Level.of(level));
      });
      

    优化四

    • 优化性能记录的缓冲器,改为1秒间隔提交
      • +记性能 +白名单较验,qps约为:15000(::对业务处理几乎无影响了)
    • 日志改为本地队列收集+批量打包提交(可称为管道模式)
      • +记性能 +记日志 +白名单较验
        * 空时1秒间隔,单包最多100个日志:qps约为:5000
        * 空时1秒间隔,单包最多200个日志:qps约为:10000

    后续尝试

    • 实验一:
      • 对比测试:日志管道模式提交,与代理抓取模式的差异

    分析总结

    • 减少IO次数,可大大提高 QPS。。。此为王道
    • 何为IO?一次IO输出过程:
      • 应用空间 -> 内核空间 -> 设备寄存器
      • 减少次数或避免IO可大大提高并发(像System.out.print...就是,都会影响高并发)
    • IO的总量有限...
      • 我们经常会看到,cpu、内存很底,但是并发压不上去。。。就是大量的IO在排队
        • 或者程序在一段时间失去了响应,过段时间又好了。。。也是大量的IO在排队
      • 业务的程序,基本上是IO密集型的
      • 不管是多线程,还是异步。。。但IO总量有限
        • 之前一直以为,异步写日志对并发没什么影响;对单次请求性能无影响,但会占用IO资源

    附:

    • 工具安装
    # centos 版
    yum install -y https://github.com/scutse/wrk-rpm/releases/download/4.1.0/wrk-4.1.0-1.el7.centos.x86_64.rpm
    
    # mac 版
    brew install wrk
    
    • 测试代码
    wrk -t10 -c200 -d10s --latency "http://10.0.0.79:1013/getAppByID?appID=10970"
    

    相关文章

      网友评论

          本文标题:关于一个简单接口的高并发测试与优化记录

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