在大规模 SOA 应用的性能测试中,一个很重要的事就是准备铺底数据。所谓铺底数据,即在性能测试之前人工地向数据库里面存入用来模拟历史的或用来测试的大量数据。
通过一个进行实际性能测试的样例,通过对有铺底数据和没有铺底数据两种情况的测试结果所进行的分析,我们发现,使用铺底数据进行性能测试,不仅可以帮助测试人员更好地发现应用系统存在的问题,同时也能够使测试结果更加接近真实生产环境下的结果。
本文假设对某大型 SOA 系统进行性能测试,要保证所有在线用户能同时在线录入档案。测试场景包括创建成员信息、收入及支出信息和提交救援案例的申请等。
在这个系统中,性能测试需要模拟很多人同时在线的情景。通过性能测试工具能模拟任意多的人同时在线,而且要保证系统性能稳定,不论任何时候都要保证系统的请求和响应时间基本保持稳定,不会随着数据库数据的增加而变慢。基于这些问题,我们需要找到一种有效的方式来对系统进行性能测试。在上面的场景中,需要一个长时间稳定的环境,这样才可以增大数据库里面的数据量,并构建负载平衡的应用服务器环境。
综上所述,可以在数据库里面存入铺底数据,在服务器端搭建集群服务器。
为什么要准备铺底数据
那么,我们该如何制作铺底数据呢?下面我们将详细地阐述这些问题。
铺底数据就是我们在做性能测试之前,在数据库里除数据库字典表外按照业务逻辑存入的大量的数据。这些数据可以被视为垃圾数据,因为它们对系统的业务逻辑没有实际影响,但对系统的性能却有着很大的影响。
我们需要按照实际的情况去生成铺底数据,而且这一过程要符合实际的生产情况表的数据比例。譬如:有一张表的数据量和另外一张表的倍数关系是 5∶1,那么准备数据的时候不论准备的数据是多少条,也需要保证这两个表的数据量的倍数是 5∶1。
虽然铺底数据是垃圾数据,但是它们同样需要遵守数据库中数据的依赖关系。比如一对一、一对多的关系等。
我们在性能测试中准备的数据如“性能测试之前在 DB2 里面准备的铺底数据表”所示。
在性能测试开始之前,我们在 DB2 数据库里面准备的铺底数据的总量是10.5 GB。
或许你会问,为什么要准备这些铺底数据?这些数据不是我们实际生产环境中出现的数据,那为什么要花时间去准备如此大量的数据呢?答案是,系统在有铺底数据和没有铺底数据的情况下,性能会有很大的差异。那么,为什么会出现这种情况呢?
首先,如果没有那些铺底数据,那么,本来为一张表建立了一个索引,当系统的数据量很小的时候,数据库就有可能进行全表扫描,而不是索引扫描,因此,如果没有铺底数据的话,有可能会造成系统发生数据库的死锁。
如果数据量比较少,数据库为了优化,有的时候就不用索引扫描,而采用全表扫描,这样造成整表被锁,导致死锁。而数据量大了以后数据库会进行索引扫描,不会锁住整个表。
所以,在有些情况下,系统上线时必须要准备一些无用的数据放在表中,让数据库不会采用全表扫描。虽然有的时候可以通过改变锁的策略去解决这个问题,但是如果存在风险,在上线系统中就要避免。
其次,如果数据量很小的话,我们不知道进行一次查询的时候, SQL 语句究竟是哪种执行路径方案。数据库有自动根据 SQL 语句算出一条自认为最优化的路径的功能,譬如 DB2 的 ACCESS PATH。ACCESS PATH 会随着数据量多少的变化而变化。一旦系统的体系结构比较庞大,那么,在日积月累中数据量会越来越大。所以要准备一定数量的数据,让 ACCESS PATH 保持相对稳定。
因为,铺底数据使得系统性能更加真实,更符合生产环境的真实情况。在数据库里面存入铺底数据,系统从一开始上线的时候,就有了一个比较稳定的环境。
如果没有铺底数据,那么系统的环境可能随时都会面临着不稳定的因素,如性能陡变、数据库异常、响应时间突然下降等。所以准备铺底数据,不但对性能测试意义深远,而且对即将上线的生产环境也是至关重要的。试想在银行系统中,如果不准备铺底数据,一旦系统上线的时候发生了问题,那么银行会损失多少客户。
准备铺底数据主要有以下几个原则:1.数据库中的数据量只要比内存大上若干倍,结果就差不多了;2.数据在准备的时候,要保持原表的约束关系;3.每张表的数据量要符合真实情况。
准备高性能铺底数据
以上介绍了铺底数据的重要性。要知道,准备的每张铺底数据表要上亿条。那么,我们如何快速而真实地准备铺底数据呢?
如果用简单的 JDBC 程序插入铺底数据,性能会很差。而用 JDBC 写一个程序往数据库里面插入数据的话,速度会很慢,大概是10万条一张表,大约需要 20 分钟。
假设我们需要准备 1 亿条数据一张表,就是 10000/10×20/60=333 小时。如果业务逻辑需要准备 20 张表,那我们准备这些数据将需要 333×20=6660 小时=277.5 天。这样的速度慢得惊人,所以通过 JDBC 准备铺底数据不行。
显然,我们需要更高效地产生铺底数据的方法。笔者所在团队选择了如下的方法:找出数据库之间的表结构关系,并据此把数据翻倍,利用 CPU 的运算能力高效率地生成的数据,并导入数据库,从而产生出所需的铺底数据。
如果要准备铺底数据,那么我们首先就要找到表与表之间的关联关系。也就是说,我们要清楚数据库里面主表和附表之间的关系是一对多或多对多,还要知道实际情况中,一张主表的一条记录大概对应附表的几条数据。只需要一个大概的规律就可以了,或者取一个中间值。我们可以通过 Rational Data Architect 生成的表结构图找到表与表之间的关系:准备原始的第一套数据(每张表大概 1000 条数据)。
我们在测试前,应该首先用 Rational Performance Tester 7.0 录制一个脚本。脚本里面包括要测试的主要用例。譬如:笔者所做的脚本一共包括10个请求,要全部按照顺序录入到 RPT 中。
然后,我们应该重新建立数据库,使数据库里面不存在数据。接下来,我们就可以利用上文叙述中录制好的 Rational Performance Tester 脚本,并循环 1000 次。这样我们的数据库里面的一些表里就会有 1000 条数据了。然后,我们在数据库里面查看哪些表中的数据增加了,然后把这些表里面的数据导出到文本文件里。