一、性能測试的概念

        性能測试是通过自己主动化的測试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行測试。负载測试和压力測试都属于性能測试,两者能够结合进行。

通过负载測试,确定在各种工作负载下系统的性能,目标是当负载逐渐添加时,測试系统各项性能指标的变化情况。压力測试时通过确定一个系统的瓶颈或者不能接受的

性能点,来获取系统能提供的最大服务级别的測试。

性能測试主要包括负载測试、强度測试、容量測试。

二、性能測试的指标

        webserver:
            Avg Rps: 平均每秒的响应次数 = 总请求数 /秒数;

            Avg time to last byte per terstion(mstes): 平均每秒业务脚本的迭代次数;

            Successful Rounds: 成功的请求;

            Failed Rounds: 失败的请求;

            Successful Hits: 成功的点击次数;

            Failed Hits: 失败的点击次数;

            Hits Per Second: 每秒点击次数;

            Successful Hits Per Second:每秒成功的点击次数;

            Failed Hits Per Second: 每秒失败的点击次数;

            Attempted Connections: 尝试连接数;

            Throughput: 吞吐率;

        数据库server:
            User Connections: 用户连接数,也就是数据库的连接数量;

            Number of Deadlocks: 数据库死锁;

            Butter Cache Hit: 数据库Cache 的命中情况;


三、性能測试的流程

        1.明白性能測试需求;

        2.制定性能測试方案;

           2.1.測试范围

           2.2.入口标准

           2.3.出口标准

           2.4.測试策略(測试环境指标、存量数据、业务场景、測试通过标准等)

           2.5.測试风险

           2.6.測试资源         

        3.设计性能測试用例;

        4.运行性能測试用例;

        5.分析性能測试结果;

        6.生成性能測试报告;


四、性能測试的工具--JMeter

        为什么是JMeter而不是LoadRunner呢  1.更少的投入,针对有限的測试成本;  2.开源工具的可定制性无可比拟;  3.通过社区得到最大程度的支持。

        JMeter是Apache组织开发的基于Java的压力測试工具。最初被设计用于web应用的測试,后来扩展到其它測试领域。

可用于測试静态和动态资源,如文件、Java服务

程序、Java对象、数据库等。JMeter能够相应用程序做功能/回归測试,通过创建带有断言的脚本来验证被測程序返回了期望的结果。并且为了保证最大限度的灵活性。

JMeter同意使用正則表達式创建断言。

        

五、JMeter的特性

        1.支持对多种服务类型进行測试;

        2.支持通过录制/回訪方式获取測试脚本;

        3.具备高可移植性,是纯Java 程序;

        4.採用多线程框架。同意通过多个线程并发取样及通过独立的线程组对不同的功能同一时候取样;

        5.精心设计的GUI支持快速用户操作和精确计时;

        6.支持缓存和离线的方式分析/回放測试结果;

        7.高扩展性;

六、JMeter经常使用測试元件

1.线程组

    用来管理运行性能測试所需的JMeter线程。

    a.能够设置线程数量

    b.设置线程启动周期

    c.设置运行測试脚本的循环次数

2.控制器

    JMeter有两种类型的控制器:採样器和逻辑控制器。

    採样器被用来向server发送请求。

JMeter採样器包括:FTP Request、HTTP Request、JDBC Request等。

    逻辑控制器用来控制JMeter的測试逻辑,特别是何时发送请求。

3.监听器

    监听器提供了对JMeter在測试期间收集到的信息的訪问方法。

4.定时器

    JMeter线程在发送请求之间没有间歇,通过加入定时器,设定请求之间应该间隔的时间。

5.断言

    能够使用断言来检查从server获得的响应内容。

6.配置元件

    配置元件与採样器紧密关联。尽管配置元件并不发送请求,但可加入或改动请求。

7.前置处理器

    会在採样器发出请求之前做一些操作。

8.后置处理器

    会在採样器发出请求之后做一些操作。

JMeter运行顺序:配置元件=》前置处理器=》定时器=》採样器=》后置处理器=》断言=》监听器

七、辅助測试工具开发

        以下的代码(工具:sqlexec)是一个用来向数据库(眼下支持Oracle、Mysql)插入測试数据的工具。支持多线程,可插入千万级别測试数据。

在兴许压測中会用到该

工具,工具开发尽量简单,一个工具仅仅完毕一个任务。同一时候不要反复制造轮子。

package d706;

/*
* sql处理
*/
public class Test_DB_Insert extends Thread{ public static String SQLTEXT = null; // 待处理的sql语句 private InputStream ins = null; // 用于读取配置文件
private Properties property = new Properties(); // 读取数据库配置文件 private String databaseType = null; // 数据库连接类型
private String driver = null; // 数据库驱动
private String url = null; // 数据库连接
private String uName = null; // 数据库登录username
private String pwd = null; // 数据库登录用户password private int numOfTestRecords; // 插入数据条数
private Connection con = null; // 连接数据库
private PreparedStatement statement = null; // 获取数据库操作对象 public Test_DB_Insert(String sql){
SQLTEXT = sql; // sql语句以參数的形式,在构造实例的时候传入
} private void init(){ // 初始化配置文件
try{
ins = new FileInputStream("./d706/dbconf.properties");
}catch(FileNotFoundException ffe){
ffe.printStackTrace();
}
try{
property.load(ins); //
}catch(IOException ie){
ie.printStackTrace();
}finally{ try{ if(ins != null) ins.close(); }catch(IOException ie){ ie.printStackTrace(); } } databaseType = property.getProperty("databasetype"); // 获取配置文件里设置的连接数据库类型 if("MYSQL".equals( databaseType.toUpperCase() )){ // 推断连接数据库类型
driver = property.getProperty("driver_mysql");
url = property.getProperty("url_mysql");
uName = property.getProperty("db_userName_mysql"); // 连接数据库的用户信息;
pwd = property.getProperty("db_pwd_mysql");
}else if("ORACLE".equals( databaseType.toUpperCase() )){
driver = property.getProperty("driver_oracle");
url = property.getProperty("url_oracle");
uName = property.getProperty("db_userName_oracle");
pwd = property.getProperty("db_pwd_oracle");
} } private synchronized void Insert_DB(){ try { try {
Class.forName( driver ); // 注冊驱动;
}catch(ClassNotFoundException cf){
cf.printStackTrace();
} con = DriverManager.getConnection(url,uName, pwd); // 获取数据库连接 con.setAutoCommit(false); // 关闭事务自己主动提交 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SS"); // 记录运行时间
TimeZone t = sdf.getTimeZone();
t.setRawOffset(0);
sdf.setTimeZone(t);
Long startTime = System.currentTimeMillis();
System.out.println("插入数据操作開始..."); statement = con.prepareStatement(SQLTEXT); //创建数据库操作对象 /*
* "INSERT INTO TEST_DB(name,sex,nickname,test1,test2,test3,test4," +
"test5,test6,test7,test8,test9,test10,test11,test12,test13,test14," +
"test15,test16,test17,test18,test19,test20,test21,test22,test23," +
"test24,test25,test26,test27,test28,test29,test30,test31,test32," +
"test33,test34,test35,test36,test37,test38,test39,test40,test41," +
"test42) VALUES(?,? ,? ,?,?,?,?,?,? ,?,?,?,?,?,?,? ,?,? ,?,? ,?,?,?,?,? ," +
"? ,? ,?,? ,?,?,?,?,?,? ,?,?,?,?,?,?,?,?,? ,? )"
*/ numOfTestRecords = 1000; //插入的測试数据量; for(int i = 0; i<numOfTestRecords; i++) { //循环
statement.setString(i + 1, "DBTest-" + i);
//statement.setString(2, "" + i%2); //0表示男 1表示女
statement.addBatch(); // 把一个SQL命令加入命令列表
//statement.executeUpdate(); //运行SQL;
}
statement.executeBatch(); //运行批量更新
con.commit();//语句运行完毕,提交事务
//int[] ref = statement.executeBatch();
//if(ref[numOfTestRecords-1] == 0){System.out.println("插入数据操作完毕");} // System.out.println("插入数据操作完毕");
Long endTime = System.currentTimeMillis();
System.out.println("插入"+numOfTestRecords+"条数据,"+"用时(时:分:秒:毫秒)" +
sdf.format(new Date(endTime - startTime))); // }catch(Exception e) {
System.out.println("异常: " + e.toString());
e.printStackTrace();
}finally{ if(statement != null){ // 关闭数据库操作对象
try{
statement.close();
}catch(SQLException se){
se.printStackTrace();
}
} if(con != null){ // 关闭数据库连接
try{
if(con.isClosed()){con.close();}
}catch(SQLException se){
se.printStackTrace();
}
}
}
} @Override
public void run() { // 类外调用 Test_DB_Insert ti = new Test_DB_Insert(SQLTEXT); // 构造实例
ti.init(); // 初始化
ti.Insert_DB(); // 运行插入数据
} // public static void main(String[] args){
//
// Test_DB_Insert ti = new Test_DB_Insert(SQLTEXT);
// ti.init(); //初始化
// ti.Insert_DB(); //运行插入数据
// } }

// 针对增删查改,可放到一个SQL处理类(Test_DB_crud)中,推断传入的SQL字符串,然后交给相应的方法去运行并在控制台输出结果。

在Test_DB_Control类

中仅仅是new一个Test_DB_crud类,形成了Test_DB_crud对Test_DB_Control的依赖关系。

package d706;
/*
*程序界面
*button事件
*/
public class Test_DB_gui extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; public static String SQLTEXT = null; // 界面输入的sql文本 private JScrollPane js = null; private JPanel jp1 = null; private JTextArea ta = null; private JButton jb = new JButton(); public Test_DB_gui(){ this.setTitle("sqlExecV1.0"); ta = new JTextArea();
ta.setText(""); js = new JScrollPane(ta);
jp1 = new JPanel();
jp1.setLayout(new BorderLayout());
jp1.add(js,BorderLayout.CENTER); jb = new JButton();
jb.setText("运行");
jb.addActionListener(this); // 加入监听 jp1.add(jb,BorderLayout.SOUTH); this.getContentPane().add(jp1); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(400,200,700,500);
this.setVisible(true); jb.addActionListener(new ActionListener(){ // button事件 public void actionPerformed(ActionEvent e) { // 匿名内部类的形式实现button事件 SQLTEXT = ta.getText(); // 将要运行的SQL设置成静态的 Multi_process mp = new Multi_process(SQLTEXT); // 在构造实例时,传入sql mp.run(); // 运行程序 //System.out.println( mp.SQLTEXT +"***"); // 控制台输出
}
});
} public void actionPerformed(ActionEvent e) {
// 实现 ActionListener 接口,须要实现的方法
} public void run() { // 运行方法 Test_DB_gui np = new Test_DB_gui();
System.out.println( np.getTitle() );
}
}
public class Multi_process {
/*
*多线程
*/
public static String SQLTEXT = null; // 待处理的sql语句 public Multi_process(String sql){
SQLTEXT = sql; // sql语句以參数的形式,在构造实例的时候传入
} public void run(){ Test_DB_Insert td1 = new Test_DB_Insert(SQLTEXT); // 创建实例
Test_DB_Insert td2 = new Test_DB_Insert(SQLTEXT);
Test_DB_Insert td3 = new Test_DB_Insert(SQLTEXT);
Test_DB_Insert td4 = new Test_DB_Insert(SQLTEXT); Thread t1 = td1; // 创建线程
Thread t2 = td2;
Thread t3 = td3;
Thread t4 = td4; t1.start(); // 启动线程
t2.start();
t3.start();
t4.start(); }
}
public class Test_Exec {
/*
* 程序入口
*/
public static void main(String[] args){
Test_DB_gui np = new Test_DB_gui();
np.run();
}
}

在Linux下运行,需打成jar包。通过shell脚本运行。以下是sqlexec的startup.sh运行脚本.

#!/bin/sh

#
#Author: bruce
#Version: sqlExecv1.0
#Date:2013-11-20
#
read -p "please input jar file path:" jarpath
java -jar "$jarpath" echo "running sqlExec."

注:

        今天突然想到測试数据的一个问题。即造出来的数据应该更接近真实。而不是都一样。所以想利用配置文件的方式,在配置文件里写好SQL,程序读取运行配置文件

并动态生成SQL。完毕插入測试数据。

这样就攻克了測试数据不够真实。可能影响測试结果的问题。---------2014年11月27日 

学习使用Jmeter做压力測试(一)--压力測试基本概念的更多相关文章

  1. 学习使用Jmeter做压力测试(一)--压力测试基本概念

    学习使用Jmeter做压力测试(一)--压力测试基本概念 一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测 ...

  2. 学习总结——JMeter做http接口功能测试

    JMeter对各种类型接口的测试 默认做接口测试前,已经给出明确的接口文档(如,http://test.nnzhp.cn/wiki/index.php?doc-view-59):本地配好了JMeter ...

  3. 学习总结——JMeter做http接口压力测试

    JMeter做http接口压力测试 测前准备 用JMeter做接口的压测非常方便,在压测之前我们需要考虑这几个方面: 场景设定 场景分单场景和混合场景.针对一个接口做压力测试就是单场景,针对一个流程做 ...

  4. (转)学习使用Jmeter做压力测试(三)--数据库测试

    数据库测试 JMeter可以做为Web服务器与浏览器之间的代理网关,以捕获浏览器的请求和Web服务器的响应,这样就可很容易的生成性能测试脚本. 根据脚本,JMeter可通过线程组来模拟真实用户对Web ...

  5. (转)学习使用Jmeter做压力测试(一)--压力测试基本概念

    一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行. 通过负载测试,确定在各种工作负载下 ...

  6. 【转】学习使用Jmeter做压力测试(三)--数据库测试

    JMeter可以做为Web服务器与浏览器之间的代理网关,以捕获浏览器的请求和Web服务器的响应,这样就可很容易的生成性能测试脚本.根据脚本,JMeter可通过线程组来模拟真实用户对Web服务器做压力测 ...

  7. 【转】学习使用Jmeter做压力测试(二)--压力测试的实施

    JMeter测试步骤: 1.建立测试计划 2.添加线程组 3.添加HTTP请求 4.增加监听器 5.执行测试计划 6.根据JMeter提供的报告分析结果 一.目标 测试访问目标服务器网站首页的每秒查询 ...

  8. 【转】学习使用Jmeter做压力测试(一)--压力测试基本概念

    一.性能测试的概念 性能测试是通过自动化的测试工具模拟多种正常峰值及异常负载条件来对系统的各项性能指标进行测试.负载测试和压力测试都属于性能测试,两者可以结合进行. 通过负载测试,确定在各种工作负载下 ...

  9. 学习总结——JMeter做WebService接口功能测试

    用JMeter作WebService接口功能测试(可以借助SoapUI来完成) SoapUI里面的操作: Wsdl文件或链接导入或添加到SoapUI打开待测请求:运行请求:取URL  SOAPActi ...

随机推荐

  1. BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

    http://www.lydsy.com/JudgeOnline/problem.php?id=4036 http://blog.csdn.net/lych_cys/article/details/5 ...

  2. stl upper_bound()

    http://blog.csdn.net/niushuai666/article/details/6734650   upper_bound( a , b , k )返回有序升序序列[a,b)中能放下 ...

  3. [转]HorizontalScrollView介绍--支持水平滚动的android布局容器

    类概述 用 于布局的容器,可以放置让用户使用滚动条查看的视图层次结构,允许视图结构比手机的屏幕大.HorizontalScrollView是一种 FrameLayout(框架布局),其子项被滚动查看时 ...

  4. Java容器-引入Guava类库

    目录 1.只读设置 2.函数式编程+组合式编程 3.约束条件 4.集合操作(并集.差集.交集) 代码实现 1.只读设置 public static void main(String [] args){ ...

  5. java中的容器解释

    解释一:容器(Container)Spring 提供容器功能,容器可以管理对象的生命周期.对象与对象之间的依赖关系,您可以使用一个配置文件(通常是XML),在上面定义好对象的名称.如何产生(Proto ...

  6. 在WPF中实现玻璃模糊效果

    在WPF中实现玻璃模糊效果还是比较简单的,主要方式如下: 添加一个Rectangle或其它控件作为玻璃放到顶部图层 将底部图像作为Brush(大多数的时候用VisualBrush)填充到Rectang ...

  7. SpringMVC 学习笔记(二) @RequestMapping、@PathVariable等注解

    版权声明:本文为博主原创文章,博客地址:http://blog.csdn.net/a67474506?viewmode=contents 1.1. @RequestMapping映射请求 Spring ...

  8. kindeditor老版本version 4.1.10 bug踩坑

    目录 上传图片或者视频的弹窗有时候不出现,只出现遮罩 视频上传无法播放的问题 参考链接: 问题目录 上传图片或者视频的弹窗有时候不出现,只出现遮罩 通过测试发现,出现这种情况不是弹出框没有出现,而是设 ...

  9. Introducing ASP.NET Core: The New ASP.NET in Town!

    The new version of ASP.NET is called ASP.NET Core (a.k.a ASP.NET 5) and it has the most significant ...

  10. Java Simon--性能瓶颈分析工具

    有了AOP以及Javainstrument之后,Java有很多很好的性能监控工具可以很有效的帮助我们分析系统瓶颈.例如使用jvisualvm的gui连接JVM应用之后可以监控应用的各种状态,可以看到每 ...