一、应用性能问题
在我们过往的测试及生产问题的分析中,常常可以发现应用执行数据库操作导致出现性能问题的情况。而这些情况中最常见的原因是SQL执行时,索引未能恰当的使用,例如未建索引、SQL条件没有利用索引、索引失效等。这些问题往往占据了性能问题的60%~80%原因。
为了应用在性能方面能安全上线,通常需要专业的性能测试及分析人员通过冗长的测试过程来进行保障,对测试人员、数据环境、测试时间等多个方面均提出了较高的要求。而组织内部往往缺乏这样的专业人员,同时互联网模式下高速的系统迭代上线也很难为专门的性能测试开展提供充足的时间资源。
为了解决这些问题,我们提出了AppTrace这套系统的设计。期望以简单、自动化、高效的手段达成在测试阶段把应用性能的这60%~80%的问题都解决掉。二、AppTrace目标
发现应用性能问题中最主要的原因之一:慢SQL
以简便的手段获取应用可能存在的SQL性能问题点
降低测试人员发现慢SQL的技术难度
使应用SQL的性能侦测覆盖率达到近乎100%
侦测分析结果与生产真实情况接近三、目标实现基本过程
1)功能测试和接口测试时,AppTrace抓取测试执行过程中的所有SQL。通过功能和接口测试实现对应用功能的全量覆盖,使得应用中的SQL几乎都会被抓取到。
2)AppTrace将抓取到的SQL请求到生产mirror库中去获取执行计划,以此获得与生产近似的执行分析结果。
3)对分析结果为疑似存在性能问题的SQL进行告警,由人工确认、优化。四、AppTrace原理及实现
4.1 AppTrace结构简介
AppTrace分为三大组件:CPTrace(CtripPaymentTrace)组件:该组件基于BTrace改造而来,用于抓取应用执行的SQL语句,并进行存储。此组件核心为两部分:CPTraceClient:作用为编译通用监控脚本,使得CPTrace Agent具备抓取应用SQL的能力。CPTraceAgent:功能为抓取应用的SQL,并将其持久化保存。AppTraceAgent组件:该组件用于将CPTrace抓取到的SQL进行解析,并通讯至AppTrace Server供其进行分析(采用MQ进行数据传输)。AppTraceServer组件:对接收到的SQL调用生产mirror库的执行计划进行解析,对解析结果按照预设规则进行性能风险判定。
4.2 AppTrace处理流程
如上图所示,通过这三大组件的协同工作将应用的SQL自动捕获并持久化存储,然后交由AppTrace Server完成执行计划的分析,根据分析结果并结合风险告警规则进行告警通知。
4.3. AppTrace的技术方案
1)动态追踪目标系统中的SQL
使用安全的JVM动态追踪工具Btrace, 按照Btrace语法编写追踪的SQL Java 脚本,指定方式如下:方法上的注解@OnMethod
Btrace使用@OnMethod注解定义需要分析的方法入口,在@OnMethod注解中,需要指定class、method以及location等,class表明需要监控的类,method表明需要监控的方法。
属性上的注解
TLS将一个脚本变量与一个ThreadLocal变量关联。
将Btrace脚本编译成字节码文件,执行命令btrace
btrace脚本,Attach API把代理包动态附加到待监控的JVM上去,通过代理包解析SQL Java 脚本。使用ASM(Java字节码操作和分析框架)修改类java.sql.Connection,java.sql.PreparedStatement,利用 JDK Instrumentation动态替换类,最后将追踪到的SQL以及参数记录到sqltrace.txt文件中,追踪的SQL如下:
2)分析SQL风险逻辑与追踪SQL逻辑的隔离
通常情况下,追踪的应用部署成功后自动运行SQL追踪插件(apptrace-agent),SQL追踪插件主要关注的是监控应用SQL以及参数,并且进行SQL与参数的匹配,最后将SQL语句存储在高速读写中间件里。对于分析队列中的SQL是否有性能风险以及告知相关负责人优化SQL,这一部分逻辑,交由SQL风险分析系统(apptrace-server)去处理。
3)分析执行计划结果以及推送告警邮件
通过DB提供的explain接口在生产备库执行explain sql,根据危险阈值分析执行计划结果确定SQL性能风险。对于分析执行计划的危险阈值需要可配置,我们提供了SQL风险告警客户端,危险阈值模块支持人工灵活修改。那么对于存在风险的SQL,采用soa email方式推送告警到测试人员以及开发负责人,直到SQL优化无风险后终止告警。
4.4 性能分析判定手段简析
对于SQL性能是否存在问题的基础判定数据,我们采用了SQL的执行计划结果。以此数据结合我们的风险阈值进行判定。
当系统上线后数据库的记录不断增加,之前写的一些SQL语句或者一些ORM操作效率变得非常低。我们会考虑SQL优化,其优化大致的流程包括:
定位执行效率低的SQL语句(定位)
分析为什么这段SQL执行的效率比较低(分析)
根据第二步分析的结果采取优化措施(解决)
而EXPLAIN命令的作用就是帮助我们分析SQL的执行情况,属于第二步。说的规范一点就是:EXPLAIN命令是查看查询优化器如何决定执行查询的主要的方法。学会解释EXPLAIN将帮助我们了解SQL优化器是如何工作的。执行计划可以告诉我们SQL如何使用索引,连接查询的执行顺序,查询的数据行数,所以通过EXPLAIN可以反映出SQL存在的风险,以及指引我们优化方向。
4.5 SQL捕获手段简析
AppTrace系统对SQL捕获的核心采用的是BTrace,根据自身需求对其进行了部分改写。
BTrace是一个为Java平台开发的安全的动态追踪工具,它为用户提供了很多注解。依靠这些注解,我们可以编写BTrace脚本(简单的Java代码),它可以在不修改原有代码的情况下动态地追踪java运行程序,通过hotswap技术,动态将跟踪字节码注入到运行类中,而不必深陷于ASM对字节码的操作中不可自拔。同时它对运行代码侵入较小,对性能上的影响可以忽略不计,所以通过Btrace在不影响应用运行前提下实时追踪程序运行的SQL,是我们后续分析SQL的基础。五、小结
追踪插件与发布平台系统集成完成,应用发布成功后自动启动插件,无需人工部署插件即可追踪SQL。目前许多应用接入了追踪插件,AppTrace确实识别到SQL风险并得到了解决,同时我们也发现了些问题。随着接入的应用越来越多,后端服务处理的数据量越来越大,服务需要进一步拓展与迭代,相信在后面的迭代中AppTrace识别SQL风险能力更精准、更全面。
【作者简介】Sedro,携程资深测试工程师,专注于测试技术探索及测试工具研发。