当前位置 : 主页 > 网络安全 > 测试自动化 >

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

来源:互联网 收集:自由互联 发布时间:2021-06-22
某项目在上线前的APT(Application Performance Testing应用程序性能测试)过程中发现性能问题,性能测试结果影响是否上线,紧急求助外部项目组技术专家。 因分属不同项目,只能通过项目

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

网友评论