UML软件工程组织

 

 

采用铺底数据进行 SOA 应用的性能测试

2008-04-18 作者:陈 鑫 ,陈 芳 来源: IBM

 
本文内容包括:
在大规模 SOA 应用的性能测试中,一个很重要的事就是准备铺底数据。所谓铺底数据,即在性能测试之前人工的向数据库里面存入用来模拟历史的或无用的大量数据。那么,为什么要准备铺底数据呢?通常情况下,准备大概每个表 1 G 的数据,数据量大概是每张表大于 5000 万条数据,如何快捷真实的准备铺底数据呢?本文还将简单介绍一下在性能测试的时候为什么需要搭建 WebSphere Process Sever (WPS) Cluster,以及如何搭建 WPS Cluster。最后,通过 Rational Performance Tester (RPT) 7 结合 WPS 集群进行性能测试,并分析比较在 WPS 服务器下的有无铺底数据支持的性能。

场景及背景介绍

本文假设对某大型 SOA 系统进行的性能测试。其中主要的测试场景是案例的申请,保证所有在线用户同时在线录入档案。测试场景包括了创建成员的信息、收入及支出信息和提交救援案例的申请。共有 10 个 web services。

在这个系统中,性能测试需要模拟很多人同时在线的情景,通过性能测试工具能模拟任意多的人同时在线,而且要保证系统性能稳定,不论任何时候都要保证系统的请求和响应时间基本保持稳定,不会随着数据库的数据的增加而变慢。基于这些问题,就需要找到一种有效的方式来对系统进行性能测试。

1. 为什么要准备铺底数据

在上面的场景中,需要一个长时间稳定的环境,那我们就可以增大数据库里面的数据量,并用一些负载平衡的应用服务器环境。综上所述,可以在数据库里面存入铺底数据,在服务器端搭建集群服务器。

那么如何制作铺底数据呢?以下的几段我们将详细阐述。

1.1 什么是铺底数据

铺底数据就是我们在做性能测试之前,在数据库里面除数据库字典表外按照业务逻辑存入的大量的数据。这些数据可以视为垃圾数据,因为它们对系统的业务逻辑没有实际的影响,但对系统的性能却有着很大的影响。

  • 铺底数据需要按照实际的情况去生成,要符合实际的生产情况的表的数据比例。譬如:有一张表的数据量和另外一张表的倍数关系是 5:1,那么准备数据的时候不论准备的数据是多少条,也需要保证这两个表的数据量的倍数是 5:1。
  • 铺底数据虽然是垃圾数据,但同样需要遵守数据库中数据的依赖关系。比如一对一,一对多的关系。

如下是我们在性能测试中准备的数据:

在性能测试之前在 DB2 里面准备的铺底数据,总量是:10.5 GB。

表 1:在性能测试之前在 DB2 里面准备的铺底数据
Table Name Data size(KB) Data Count
Interested_party 3,630,594 7,730,000
Address 178,600 1,230,000
Interested_party_type_association 760,719 7,720,000
Household_member 546,328 4,487,000
Household 28,840 1,239,000
Document 610,632 5,251,000
Interested_party_association 542,390 4,958,000
Interested_party_address 99,602 1,232,000
Contact_phone 143,581 1,232,000
Address_contact_phone 109,356 1,232,000
Case 269,039 2,479,000
Case_document_association 22,731 1,235,000
Case_party_association 537,562 4,958,000
Evidence 2,793,073 43,295,000
evidence_party_association 796,680 43,295,000

1.2 有没有铺底数据的性能会有很大差异

或许你会问,为什么要准备这些铺底数据?这些数据不是我们的实际生产环境的数据,那为什么要花时间去准备如此大量的数据呢?

答案是,系统在有铺底数据和没有铺底数据的情况下,性能会有很大的差异。那为什么会这样呢?

  • 首先,如果没有那些铺底数据,那么本来为一张表建立了一个索引,当系统的数据量很小的时候,数据库就有可能造成全表扫描,而不走索引扫描,这样就会造成系统的性能降低。
  • 如果数据量很小的话,我们不知道进行一次查询时候的 SQL 语句究竟是哪种执行路径方案。(数据库有自动根据 SQL 语句算出一条自认为最优化的路径的功能。譬如 DB2 的 ACCESS PATH。ACCESS PATH 会随着数据量的多少的变化而变化的。一旦系统比较庞大,在日积月累中,数据量会越来越大的。所以要准备一定数量的数据,让 ACCESS PATH 保持相对稳定。

1.3 没有铺底数据有可能造成系统发生数据库的死锁

如果数据量少,数据库为了优化有的时候就不用 INDEX 扫描,而采用全表扫描,这样造成整表被锁,导致死锁,而数据量大了以后数据库会进行 INDEX 扫描,所以不会琐住整个表。所以在有些情况下在系统上线时准备一些无用的数据放在表中,让数据库不会导致全表扫描!虽然有的时候可以通过改变锁的策略去解决这个问题,但是如果存在风险,在上线系统中就要避免。

1.4 铺底数据使得系统性能更加真实 , 更符合生产环境的真实情况

在数据库里面存入铺底数据,系统从一开始上线的时候,就已有了一个比较稳定的环境。如果没有铺底数据,那系统的环境可能随时面临着不稳定的因素:如性能陡变,数据库异常 ( 资源池不够用,数据库死锁,数据库全表扫描等等 ),响应时间突然下降。所以准备铺底数据,不但对性能测试意味深远,而且对即将上线的生产环境也是至关重要的。试想在银行系统中,如果不准备铺底数据,一旦系统上线的时候发生了问题,那么银行会损失多少客户!

1.5 准备铺底数据要则

准备铺底数据主要有以下几点原则:

  • 准备的数据量大小:数据库中的数据量只要比内存大上若干倍,结果就差不多了。
  • 数据在准备的时候,要保持原表的约束关系。
  • 每张表的数据量要符合真实情况(对此点要求可能比较高 , 通常的做法是估算一下实际的情况)。

介绍了这些的原则,如何在实际操作中创建铺底数据呢?后面的第 2 章将结合上述的三条原则,具体讲述如何高性能地准备铺地数据。

2. 高性能准备铺底数据

以上介绍了铺底数据的重要性。要知道准备的铺底数据每张表要上亿条,那么我们如何快速而真实的准备铺底数据呢?这章将详细展开讲解。

2.1. 如果用简单的 JDBC 程序插入铺底数据 , 性能很差

用 JDBC 写一个程序往数据库里面插入数据的话,速度会很慢,大概是十万条一张表需要 20 分钟。那假设我们需要准备 1 亿条数据一张表就是 10000/10*20/60=333 小时,如果业务逻辑需要准备 20 张表,那我们准备这些数据将需要 333*20=6660 小时 =277.5 天!这样的速度慢得惊人,所以通过 JDBC 准备铺底数据将不成立。

2.2. 高效率生成铺底数据

显然,我们需要能更高效产生铺底数据的方法。笔者所在团队选择了如下的方法:找出数据库之间的表结构关系,并据此把数据翻倍利用 CPU 的运算能力高效率生成的数据导入到数据库中,从而在数据库中产生出所需的铺底数据。通过这种方式即避免了采用编写 JDBC 程序的方式,又能高效地生成铺底数据。

2.2.1. 找到数据库之间的表结构关系

要准备铺底数据首先要找表与表之间的关系,也就是要清楚在数据库里面的表之间的主表附表关系:一对多,多对多的关系。还有要知道实际情况中,一张主表的一条记录大概对应附表的几条数据。只需要一个大概的规律就可以了,或者取一个中间值的比例。我们可以通过 Rational Data Architect 生成的表结构图找到表与表之间的关系:

如下图所示:

图 1. 找到表与表之间的关系
找到表与表之间的关系

从上图(注:上图可以在需求文档中得到)可以看出里面的 7 张表 A_S_HIS,A_ST,A_I,A,A_T,A_S,A_S_T 中,我们先要导入的三张表:A_ST,A_T, A_S_T,其次要导的表是 A,最后要导入的三张表是 A_S_HIS,A_I, A_S。顺便说一下,我们还要保证后导入的表的引自先前导入表的主键须和主表的引它作为外健的条目有对应关系,最好是保持一致。

2.2.2. 准备原始的第一套数据 ( 每张表大概 1000 条数据 ).

首先利用 Rational Performance Tester 7.0 录制一个脚本。脚本里面要包括要测试的主要用例。譬如:笔者所做的脚本一共包括十个请求,要全部按照顺序录入到 RPT 中。

然后,重新建立数据库,使数据库里面不存在数据。

接下来,就可以利用上文录制好的 Rational Performance Tester 脚本循环 1000 次。这样我们的数据库里面的一些表里就会有 1000 条数据了。然后我们从数据库里面查看哪些表中的数据增加了,然后把这些表里面的数据导出到文本文件里。

如图所示:

图 2. 把这些表里面的数据导出到文本文件里
把这些表里面的数据导出到文本文件里

注意:对于每张变化的表,我们都要导出它所对应的文本文件。例如:表 casee 对应的文本文件是 casee.sql。

2.2.3. 程序扩大数据至每张表千万条 .

编写程序把每张表对应的文本文件 ( 例如:casee.sql) 的数据成比例扩大 10000 倍,要注意处理表里面的主键的唯一性还有依赖性,保证表和表的一对一关系和一对多关系。首先我们利用 DB2 找到个表的依赖关系:

图 3. 利用 DB2 找到个表的依赖关系
利用 DB2 找到个表的依赖关系

从上图中我们可以看到表 CASEE 和很多表都有关系,也就是说它的一些字段在图里面的很多表里面或者做主键,或者做外键。如果 CASEE 里面的字段是图中所示表里面字段的外键,那就需要一一对应了。在程序设计的时候就要保证这两张表的字段和字段里面的值保持一致。

接下来就是写一个程序去把每张表的数据翻倍,笔者在此提供一套思路供大家参考:

  • 我们找到需要表的主键字段以后,让这个字段的数据不要重复,通常都是用数字表示的。建议从 10000000 开始增加,这样可以避免铺底数据和我们的实际数据主键重复。
  • 生成数据的时候要用 BufferedReader,BufferedWriter 去读写文件。
  • 生成的数据一定要保持主键唯一,还要满足字段的各种约束,否则会导致数据导入后无法 active。

2.2.4. 把数据导入到数据库中

将数据 IMPORT 到 DB2 里面,注意不要用 load,因为 load 需要数据之间有约束关系,这样效率会低很多倍。而 IMPORT 不需要依赖关系,因为数据在数据库里面还没有被 ACTIVE。

如下所示:

图 4. 把数据导入到数据库中
把数据导入到数据库中

2.2.5. 将数据库的表置成 ACTIVITY

建好的数据库,需要把表 ACTIVITY,并且 REORG 一次数据库里面的数据。这样使得数据库的查询路径可以优化。

如下所示:

图 5. 将数据库的表置成 ACTIVITY
将数据库的表置成 ACTIVITY

2.2.6. 重建表的索引

为数据库里面的表建立一些适当的索引,并且要调整一些数据库的参数,如缓冲池,连接池等。

到此为止,铺底数据就准备好了。

3. 结合铺底数据基于 WPS Cluster 服务器的性能测试试验

3.1 性能测试环境准备

在本文中,准备采用这样的测试环境:IBM WebSphere Process Sever 集群做应用服务器,IBM DB2 做数据库,Rational Performance Tester 7.0 做性能测试工具,IBM HTTP Server 做 HTTP Server。

3.1.1 什么是 WPS Cluste 及其作用 , 以及 WPS Cluster 的搭建

  • Cluster 集群

一组相互独立的服务器在网络中表现为单一的系统,并以单一系统的模式加以管理。此单一系统为客户工作站提供高可靠性的服务。大多数模式下,集群中所有的计算机拥有一个共同的名称,集群内任意系统上运行的服务可被所有的网络客户所使用。Cluster 必须可以协调管理各分离的组件的错误和失败,并可透明地向 Cluster 中加入组件。一个 Cluster 包含多台(至少二台)拥有共享数据存储空间的服务器。任何一台服务器运行一个应用时,应用数据被存储在共享的数据空间内。每台服务器的操作系统和应用程序文件存储在其各自的本地储存空间上。Cluster 内各节点服务器通过内部局域网相互通讯。当一台节点服务器发生故障时,这台服务器上所运行的应用程序将在另一节点服务器上被自动接管。当一个应用服务发生故障时,应用服务将被重新启动或被另一台服务器接管。当以上的任一故障发生时,客户都将能很快连接到新的应用服务上。

WPS 的集群就是基于 WPS 服务器建立的集群。

  • Clus ter 集群的作用:

利用集群我们可以增大 JVM 紧张的问题,可以分摊 I/O 的负载量,还可以把系统的故障率成万倍的降低。假如一台 Server 的稳定性是 0.99,那么系统 DOWN 掉的几率就是 0.01,那么如果我们两个 Server 在一起的集群环境的不稳定性将降低到 0.00001,也就是有两个 Server 的集群环境的稳定性提高到 0.9999。这样我们就可以根据实际生产环境的要求来降低系统的风险性。

  • WPS Cluster 集群的 搭建:

本测试环境中我们就采用了 WPS 集群(WPS Cluster)。Cluster(集群)是多个 WPS 的集群,它可以集中管理所有 WPS,并参与管理所有 WPS 的负载。WPS 6.0.1 及以上版本支持搭建 Cluster。这样可以做到负载均衡(Workload Balance)和高可用性(High Availability),从而使得 WPS 更加稳定,性能更为优秀。况且在一般的真实生产环境中,WPS 集群也是经常要使用到的。

以下是本测试环境中 WPS Cluster 的拓扑图:

图 6. WPS Cluster 的拓扑图
WPS Cluster 的拓扑图

Cluster 分为两种,水平 Cluster 和竖直 Cluster。水平 Cluster 的成员在不同物理机器上,竖直 Cluster 的成员在同一台物理机器上。在这里由于测试环境的限制,我们采用的是竖直 Cluster,有三个 Cluster 成员。Cluster 中有一个 Deployment Manager 类型 profile,它可以管理整个单元内部所有的 WPS。Deployment Manager 通过和 Node Agent 交互信息来管理节点。而 Node Agent 用来管理三个 Cluster 成员。我们还需要在 WPS Cluster 和应用中间加入一个 HTTP Server,使得应用通过 HTTP 协议访问 WPS Cluster 的时候随机的分摊到不同的 Cluster 上面。

3.1.2 性能测试环境的准备

在理想的情况下,性能测试的环境最好能够完全模拟真实应用部署的环境,以便于通过性能测试得到应用在真实生产环境下的性能结果。然而由于真实应用部署环境的规模比较大,这是不实际的。因此,为了能够得到更具真实性的性能结果以及更好地发现应用存在的性能问题,我们在测试中采用可控制的测试环境来尽量模拟真实环境,其中也包括对历史数据的准备。在我们的测试环境中,为了更好地分析数据库和应用本身的性能问题,如 I/O 问题,将 WPS 和数据库将分别安装在不同的物理机上。

如下是性能测试环境的拓扑图:

图 7. 性能测试环境的拓扑图
性能测试环境的拓扑图

首先通过 HTTP 请求到 HTTP Server ,再进入 UI 层,然后通过 UI 调用 Web Service,Web Servive 再通过 HTTP Server 调用一些 BPEL 和 WSDL 文件,再通过 JDBC 连接 Database,并用 Content Manager 存入一些文件(如 PDF,Word)到 Database 上。

利用 IBM HTTP Server 做 HTTP Server,WebSphere Application Server 上搭建 UI 层,将 BPEL WSDL 搭建到 WebSphere Process Server 上,并用 DB2 做 Database。现在整个测试环境就基本搭建完成。

3.2 在 Rational Performance Tester 中生成测试脚本

3.2.1 Rational performance tester 介绍

在本文中用来进行性能测试的工具采用的是 IBM 的 Rational Performance Tester。它是用于生成用户负载的商业化的 IBM 产品。它作为 IBM 软件开发平台(software development platform,SDP 的一个插件,并且目前只支持在 Microsoft® Windows® 操作系统和 Linux 上使用。Rational Performance Tester 包括一个 IBM Rational ClearCase LT 的完整功能的副本,再加上以下这些关键特性:

  • 用于创建、修改,并执行工作负载的可视化测试编辑器。
  • 能够同时运行多个,以及各种各样的用户模拟。
  • 跨节点分配测试作业的可部署的执行代理。
  • 立即的性能及吞吐量报告。
  • 动态服务器响应的自动识别,及对其的支持。
  • 使用数据池随机的输入。
  • 服务器资源数据的集合及可视化。
  • 生成在测试记录过程中被访问的 Web 页面的 HTML 视图。
  • 为了灵活定制测试,可以插入 Java 代码。

用 Rational performance tester 创建一个申请案例的页面测试,并命名 Project Name 为 MAR。

图 8. 创建一个页面测试
创建一个页面测试

通过访问 Manage Application Request 的 Web 页面,执行一个完整的申请流程,来完成 Rational performance tester 的测试脚本的录制。在 Test 的内容框可以看到,录制的测试脚本共包含 11 个页面。

图 9. 录制的测试脚本共包含 11 个页面
录制的测试脚本共包含 11 个页面

3.2.2 创建性能调度

性能调度使得你可以对测试分组,排序,以及在远端运行测试。时间计划可以简单到每一个虚拟用户运行一个测试,也可以复杂至在不同的组中有上百个虚拟用户,每一个都在不同的时间运行不同的测试。利用性能调度,你可以:

  • 对测试分组来仿真不同用户操作。
  • 设置测试运行次序:顺序地,随机地,或按照所带权值的次序。
  • 设置每个测试运行次数。
  • 依照一定的速率运行测试。
  • 在远端运行一个或多个测试。

这里创建一个名为 schedule 性能调度,由于这次测试都是在本机执行,并且都执行同一个测试脚本,所以创建一个 User Group,其中包含并发用户 5 个。为保证用户的真正并发性,注意要将每个 user 之间的 delay time 设置为 0 Sec,think time 也设置为 0 Sec。测试执行次数设为 10 次。

图 10. 创建一个名为 schedule 性能调度
创建一个名为 schedule 性能调度

性能调度设置完成后,执行性能调度。

图 11. 执行性能调度
执行性能调度

首次执行的测试是在数据库为空的情况下进行的,然后按照本文第二部分介绍的方法,向数据库中插入铺底数据。插入铺底数据后,同样的方法,再次执行一遍 schedule 性能调度,与之前执行的结果进行比较。

3.3 分析测试结果

通过分别对没有铺底数据和有铺底数据的情况进行相同的性能测试,会发现测试结果有很大的区别,主要表现在页面平均响应时间。经过测试,在没有铺底数据的情况下,平均页面响应时间是 58.552 ms,而在有铺底数据的情况下,平均页面响应时间是 608.344 ms,具体从 Rational Performance Tester 生成的测试报告中可以清楚地看到每个页面的平均响应时间。

3.3.1 没有铺底数据的测试结果

图 12. 没有铺底数据的测试结果
没有铺底数据的测试结果

3.3.2 有铺底数据的测试结果

图 13. 有铺底数据的测试结果
有铺底数据的测试结果
 

3.3.3 分析比较测试结果不同的原因

从上面两个页面平均响应时间图的对比,可以看出在有铺底数据的情况下,平均响应时间均高于没有铺底数据的测试结果,其中 start 和 Manage Application Request (7) 这两个页面的响应时间差距比较大,并且普遍高于其他页面。经过查找问题根源,发现这是由于在这两个页面中,在数据库中进行了大量视图创建和 select 语句的操作,从而导致响应时间比较长。

因此从上述比较可以看出,在有铺底数据的情况下进行性能测试,能够帮助测试人员更好地发现被测应用系统存在的问题。另外,一般应用在真正生产系统中运行时,都会存在大量的历史数据。这样我们在测试时就加入铺底数据,不仅能够得到更加真实的测试结果,并且能够及早发现应用系统中存在的隐患,不会在系统正式运行后才发现问题,那时已经为时已晚。

4. 总结

在本文中,介绍了什么是铺底数据、准备铺底数据的重要性,以及如何运用 Ratioanl Performance Tester 7.0 和 DB2 的导入功能高效生成铺底数据的方法。并且提供了一个实际性能测试样例,对一个基于 WebSphere Process Sever 的应用程序的性能测试进行了详细描述,并且,对有铺底数据和没有铺底数据的两种情况的测试结果进行了分析,发现使用铺底数据进行性能测试,不仅可以帮助测试人员更好地发现应用系统存在的问题,同时也能够使测试结果更加接近真实生产环境下的结果。

参考资料

学习 获得产品和技术
 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号