应用性能问题解决实际案例

发表于:2019-6-12 13:40

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Richard崔驰坤    来源:博客园

  某项目在上线前的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在本地进行性能测试。
  HttpClient和HttpWebRequest性能比较
  测试环境
  测试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的使用都是后期由开发组告知)和所使用的技术,才能给出全面建议。从开发组角度应该训练发现性能问题的敏感度。所有问题的发现和解决以测试事实数据说话,不会存在莫须有的性能问题,所有问题皆有因缘。

     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号