某项目在上线前的APT(Application Performance Testing应用程序性能测试)过程中发现性能问题,性能测试结果影响是否上线,紧急求助外部项目组技术专家。

因分属不同项目,只能通过项目组提供的信息进行分析。

第一轮评审

根据APT性能监控截图,左图为并发用户数和CPU使用率,右图为单独的CPU使用率情况。APT测试情景为并发用户数以5分钟为周期进行增加,增加用户数25人,在40分钟后达到最终200并发用户并保持1小时200用户活动状态。

很明显看出用户稳定后CPU使用率还在持续增长,怀疑有内存泄露问题。

分析

第一轮我们拿到的是API源代码,日志里面出现outOfMemory错误,检查一遍发现API控制器方法中创建了HttpClient实例。询问开发组回复是因为每次请求URL不同,根据经验推荐采用HttpWebRequest替换调HttpClient。同时我们调查是否是由HttpClient引起的内存泄漏问题。

由Google搜索结果HttpClient确实有内存泄漏的报告,我们着手写了一个小程序比较HttpClient和HttpWebRequest性能,并通过JMeter在本地进行性能测试。

HttpClientHttpWebRequest性能比

测试环境

测试URL: https://www.baidu.com/#{number} (number变量为随机或递增以防止HTTP缓存干扰性能对比结果)

测试节奏:10秒周期,并发用户从1到200增长

测试结果(内存使用量)

  • HttpClient: 455MB

  • HttpWebRequest: 242MB

图1: HttpClient (GetAsync)

图2: HttpWebRequest (请忽略结尾处由网络连接问题出现的凸起)

结论

将HttpClient更换使用HttpWebRequest,但根据HttpClient内存使用陡增幅度估计还有其它问题,通知开发组继续调查并提供相关资料。

第二轮评审

比较IIS内存使用和SQL Server的内存使用发现相同的增长趋势,猜测瓶颈出现在数据库查询中(如果是拒绝访问数据库不会出现内存增长,一定是已经连接了数据库并产生查询问题导致)。

推荐增加查询操作日志获得查询执行时间,安装数据库性能监视工具(可使用Windows Server自带的Performance Monitor或者第三方工具如AppDynamic),查看查询的执行计划(Execution Plan)。

图3: SQL Server – 内存 - % committed Bytes (内存使用)

图4: MS IIS – 内存 - % Committed Bytes (内存使用)

同时经过了解API还会调用上游系统的API(API嵌套),所以考虑检查日志是否存在因上游API瓶颈导致调用失败,导致异常阻塞请求进程。也会出现相同的现象,开发组着手调查。

上游API问题通过调整系统配置消除瓶颈,但SQL Server性能问题还无任何头绪。只能安排时间一起评审数据库及相应查询性能问题。

第三轮评审

背景

测试总时长1小时40分:从最开始每隔1分钟增长5个并发用户,40分钟左右并发数加到200,然后维持并发用户不变,又执行1小时

现象

达到200并发后的20分左右时, CPU的使用率达到30% 左右之后保持相对平稳的比例,但是在这之后的执行过程中 request queued 曲线出现排队现象, Thread Count 曲线出现突然增长的情况,并且同是response time 翻倍增长。

上次报告没有HTTP 5xx错误,本次出现HTTP 5xx错误,27日错误数量激增。

程序中有从上百万条数据中抽取数据生成级联选择(下拉菜单)的UI元素。

程序中使用了Http Cache,但在准备Cache数据的逻辑中没有锁处理,数据准备时间过长,就会造成期间大量请求访问数据库。

性能测试报告中SQL Server也显示出周期性达到100% CPU利用率,引发数据库连接超时,同时应用程序出现GATEWAY_TIMEOUT。

System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.

分析

因已经做过两轮评审,开发组这次提供了全面的资料,通过代码评审发现逻辑中有使用LDAP(Windows活动目录轻量目录访问协议Light Directory Access Protocol)遍历登陆者所有活动目录下的组。

此逻辑可能会产生请求ADFS查询的瓶颈,阻塞请求。

同时发现部分被查询的表中没有创建索引(这个是在最初问过开发团队但得到的回答是肯定的)并进行索引优化,另外,API采用.NET Entity Framework编写,由SQL查询监控看出因无索引导致EF生成相同表的嵌套(笛卡尔积)查询,是导致表遍历和产生表锁的主要原因。

对于大量出现的5xx错误,因上次性能测试没有,主要针对修改的代码进行评审发现增加了EF查询逻辑,这也是导致循环嵌套的原因。

结论

表索引优化是主要解决办法。EF查询最终改为明文查询并SQL查询优化。

总结

性能问题首先由测试入手,根据测试报告发现错误和性能瓶颈,主要以解决错误消除瓶颈为主要原则。对于有数据库存在的情景,注意查询和索引优化,保证连接池有效支持应用并发。问题调研期间要了解整体架构(本次API嵌套问题和LDAP的使用都是后期由开发组告知)和所使用的技术,才能给出全面建议。从开发组角度应该训练发现性能问题的敏感度。所有问题的发现和解决以测试事实数据说话,不会存在莫须有的性能问题,所有问题皆有因缘。

原文地址:https://www.cnblogs.com/richardcuick/p/11008387.html

应用性能问题解决实际案例相关推荐

  1. SQLServer访问Oracle查询性能问题解决

    原文:SQLServer访问Oracle查询性能问题解决 1. 问题 系统有个模块,需要查询Oracle数据库中的数据.目前是通过建立链接服务器实现的. SQLServer访问Oracle实现 可参考 ...

  2. 一个MySQL 5.7 分区表性能下降的案例分析

    告知MySQL5.7.18的使用者分区表使用中存在的陷阱,避免在该版本上继续踩坑.同时通过对源码的讲解,升级MySQL5.7.18时分区表性能下降的根本原因,向MySQL源码爱好者展示分区表实现中锁的 ...

  3. SQL SERVER 2012 执行计划走嵌套循环导致性能问题的案例

    开发人员遇到一个及其诡异的的SQL性能问题,这段完整SQL语句如下所示: declare @UserId INT declare @PSANo VARCHAR(200) declare @ShipMo ...

  4. 通过改进算法来优化程序性能的真实案例(Ransac)

    对于运行不了几次,一次运行不了多久的方法,我们不需要考虑性能优化,对于那些需要经常运行几百次几千次的方法,我们头脑里还是要有性能这根弦.C#太优雅方便了,以至于很多人写程序时根本就把性能抛到脑后了,不 ...

  5. 性能优化实战案例——助力某移动OA系统

    前言 最近连续接触了4个OA系统,均存在着不同的性能问题,本文记述对某移动OA系统的优化全过程,让看官们对数据库优化流程有一个了解,并揭开隐式转换这无情杀手的神秘面纱. 本文使用的工具:SQL专家云平 ...

  6. mysql 5.5 性能测试,MySQL 5.5迁移到5.7的性能问题排查案例

    最近和同事排查了一个MySQL的SQL性能问题.问题的背景是有一个业务的数据库从MySQL 5.5迁移到了MySQL 5.7,原来在5.5中有一个SQL秒级就能完成,但是在5.7版本中执行时间长了好多 ...

  7. 系统迁移性能问题解决

    最近公司系统由原来小机迁移到IDC机房,应用在虚拟机环境下运行,出现了性能问题,表现为用户上来之后系统承受不住压力而宕机,打不开界面. 经过一周的各种尝试,最终得以解决,记录一下以免下次犯同样的错误, ...

  8. Java 性能优化实战案例分析:Redis如何助力秒杀业务

    在上一课时,我们以 Guava 的 LoadingCache 为例,介绍了堆内缓存的特点以及一些注意事项.同时,还了解了缓存使用的场景,这对分布式缓存来说,同样适用. 那什么叫分布式缓存呢?它其实是一 ...

  9. mybatis批量插入oracle大量数据记录性能问题解决

    环境: mybatis + oracle11g r2 1.使用"直接路径插入"(下面sql语句中的"/*+append_values */"),并且使用关键字& ...

最新文章

  1. Redis初学:1(NoSQL的简介和Redis的安装)
  2. 第二章 序列比对——Blast局部比对
  3. 果园机器人的课文_小学三年级下《果园机器人》课文
  4. 前端CSS基础7.8
  5. tomcat启动时错误:Cannot rename original file to *.tomcat-users.xml.old
  6. go语言操作xlsx文件
  7. 在Xcode6中搭建Python开发环境
  8. 前端学习(3198):jsx语法规则2
  9. SpringBoot2 Spring Cloud consul 分布式配置中心使用教程
  10. 原生JavaScript使用和jQuery使用
  11. 电视android怎么连接手机助手下载,投屏助手app下载 投屏助手(手机投屏到电视) for Android v2.0 安卓版 下载-脚本之家...
  12. Java、JSP公文流转系统
  13. 树莓派4B 安装卸载pip、pip3
  14. RESULT:0x80029C4A (TYPE_E_CANTLOADLIBRARY))
  15. 如何隐藏QDockWidget的标题栏
  16. mysql微信昵称存储_mysql保存微信昵称特殊字符的方法
  17. pytorch einsum, numpy einsum
  18. 指纹识别零日攻击的仿真器
  19. Applications for PacBio circular consensus sequencing
  20. 049--python--多人聊天室案例

热门文章

  1. 读名老中医之路笔记(二)
  2. Zabbix server is not running
  3. 【python】-- Django 中间件、缓存、信号
  4. RabbitMQ详解(三)
  5. Objective-C 学习记录6--dictionary
  6. Shell练习题(持续更新)
  7. Asymptote 学习记录(2):例子阅读
  8. java网络编程 个人心得
  9. 在C#中使用SQLite
  10. Autofac实现有条件的DI