Jmeter jdbc接口测试

Posted duaner92

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jmeter jdbc接口测试相关的知识,希望对你有一定的参考价值。

一,jmeter工具介绍  

  JMeter也称为“Apache JMeter”,它是一个开源的,100%基于Java的应用程序,带有图形界面。 它旨在分析和衡量Web应用程序和各种服务的性能和负载功能行为。

JMeter主要用于测试Web应用程序或FTP应用程序,但目前,它适用于功能测试,JDBC数据库连接,Web服务,通用TCP连接和OS本机进程。 您可以执行各种测试活动,如性能,负载,压力,回归和功能测试,以便针对您的Web服务器获得准确的性能指标。

JMeter支持的协议列表:

  • Web Services - SOAP / XML-RPC
  • Web - HTTP, HTTPS sites ‘web 1.0’ web 2.0 (ajax, flex 和 flex-ws-amf)
  • 通过JDBC驱动程序的数据库
  • 目录 - LDAP
  • 通过JMS面向消息传递的服务
  • 服务 - POP3, IMAP, SMTP

运行环境:

  windows 10

  Jmeter 1.5.0(不支持jdk1.7)

  jdk 1.8.0_101

  impala 2.9.0-cdh5.12.2

  kerberos 1.15.1-19.el7

二,安装(以winsows为例)

  1. 下载网址:http://jmeter.apache.org/download_jmeter.cgi

  2. 解压到:C:\\jmeter\\apache-jmeter-5.0

  3. 运行:

        windows :C:\\jmeter\\apache-jmeter-5.0\\bin\\jmeter.bat 双击

  linux : chmod a+x  ..../bin/jmeter.sh

      4. 说明:本人使用Jmeter测试Kerberos认证的impala 21050接口,参考网上修改bin/下的krb5.conf和jaas.conf,没有成功。参考源码,发现jdbc代码块中没有涉及到Kerberos认证,故推测Kerberos不适用jdbc。

  解决办法:采用自定义Java测试类,放入Jmeter中进行测试。

(1)编写Java测试类

  • 环境准备:myeclipse,jdk 1.8,ApacheJMeter_core.jar  (jmeter安装目录/lib/ext),ApacheJMeter_java.jar(jmeter安装目录/lib/ext)
  • 创建ImpalaJDBCJmeter类,代码如下
package JDBC;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ImpalaJDBCJmeter extends AbstractJavaSamplerClient{

	/**
	 * @param args
	 */
	 private SampleResult results;  
	 private String arg1; 
	 
	 /* Implements JavaSamplerClient.setupTest(JavaSamplerContext) 
	  * 每个线程测试前执行一次,做一些初始化工作
	  * */  
	    public void setupTest(JavaSamplerContext arg0) {  
	  
	        results = new SampleResult();  
	        results.setSamplerData(toString());  
	        results.setDataType("text");  
	        results.setContentType("text/plain");  
	        results.setDataEncoding("UTF-8");  
	  
	        results.setSuccessful(true);  
	        results.setResponseMessageOK();  
	        results.setResponseCodeOK();  
	          
	        arg1 = arg0.getParameter("arg1", "");  
	        if (arg1 != null && arg1.length() > 0) {  
	            results.setSamplerData(arg1);  
	        }  
	    }  
	    
	    /* Implements JavaSamplerClient.teardownTest(JavaSamplerContext)
	     * 测试结束时调用
	     * */  
	    public void teardownTest(JavaSamplerContext arg0) {  
	        System.out.println("treaddown");  
	    } 
	    
	    /* Implements JavaSamplerClient.getDefaultParameters()
	     * 设置可用参数及的默认值
	     *  */  
	    public Arguments getDefaultParameters() {  
	        Arguments params = new Arguments();  
	        params.addArgument("arg1", "select * from duan"); // 定义一个参数,显示到Jmeter的参数列表中,第一个参数为参数默认的显示名称,第二个参数为默认值  
	        return params;  
	    }  
	    
	    /**
	     * 开始测试,从arg0参数可以获得参数值;
	     */
	    
	    public SampleResult runTest(JavaSamplerContext context) {  
	        int len = 0;  
	        results.sampleStart(); // 定义一个事务,表示这是事务的起始点,类似于LoadRunner的  
	                                // lr.start_transaction  
	        arg1 = context.getParameter("arg1");  
	        doJDBCDeal(arg1);
	        results.sampleEnd(); // 定义一个事务,表示这是事务的结束点,类似于LoadRunner的 lr.end_transaction  
	        return results;  
	    }   
	    
	    //kerberos认证
	    
	    private static Map map = new HashMap();
		 private static Logger logger = LoggerFactory.getLogger(impalaJDBCKERBEROS.class);
		 
		 public static synchronized Properties getProperties(String path) {
				Properties prop =null;
				if(!map.containsKey(path)){
					prop= new Properties();
					InputStream in = null;									
					try {
						in = impalaJDBCKERBEROS.class.getResourceAsStream(path);
						prop.load(in);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}finally {
						try {
							if(null!=in){
							in.close();
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}else{
					prop = (Properties)map.get(path);
				}
				
				return prop;
			}
		 
		 public static String getValue(String key,String path){
				return getProperties(path).getProperty(key);
			}
		 
		 public static Configuration loginkerberos() throws IOException {
				Configuration conf = new Configuration();
				conf.addResource("hive-site.xml");
				System.out.println(conf.get("hive.metastore.kerberos.principal"));

				String principal = "test@HADOOP.COM";
				String keytabLocation = null;
				String name = System.getProperty("os.name");
				System.out.println("operation system:" + name);
				if (name.startsWith("Windows")) {
					System.setProperty("java.security.krb5.conf",
							impalaJDBCKERBEROS.getValue("java.security.krb5.conf.forwin", "/SysConfig.properties"));
					keytabLocation = impalaJDBCKERBEROS.getValue("keytab.file.forwin", "/SysConfig.properties");
				} else {
					System.setProperty("java.security.krb5.conf",
							impalaJDBCKERBEROS.getValue("java.security.krb5.conf.forlinux", "/SysConfig.properties"));
					keytabLocation = impalaJDBCKERBEROS.getValue("keytab.file.forlinux", "/SysConfig.properties");
				}

				//conf.set("hadoop.security.authentication", "kerberos");
				UserGroupInformation.setConfiguration(conf);
				UserGroupInformation.loginUserFromKeytab(principal, keytabLocation);
				// UserGroupInformation loginUser = UserGroupInformation.getLoginUser();

				return conf;
			}
		 
				
				private static Configuration conf = null;
				private static ExecutorService poolx = Executors.newFixedThreadPool(50);
				static {
					try {
						/**
						 * 每次查询,每次认证一次,放开下面注释的一行
						 */
						conf =impalaJDBCKERBEROS.loginkerberos();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
	    
	    public void doJDBCDeal(String sql) {  
	    	
	        try { 
	            Class.forName("org.apache.hive.jdbc.HiveDriver");  
	        } catch (ClassNotFoundException e) {  
	            e.printStackTrace();  
	        }  
	        Connection conn = null;  
	        Statement stm = null;  
	        ResultSet rs = null;  
//	        String sql = "select * from duan";  
	        try {  
	            conn = DriverManager.getConnection("jdbc:hive2://duan140:21050/default;principal=impala/duan140@HADOOP.COM;AuthMeth=1");  
	            stm = conn.createStatement();  
	            rs = stm.executeQuery(sql);  
	            results.setResponseCode("testStr:" + arg1);  
	            results.setResponseMessage("aaaaaaaaaaaaaaa");  
	              
	            results.setResponseCode("UTF-8");  
	            results.setResponseCodeOK();  
	            results.setResponseData(("execute:"+ sql+ "\\r\\n" + rs2Str(rs)).getBytes("utf-8"));  
	        } catch (Exception e) {  
	            results.setSamplerData(e.getMessage());  
	            results.setSuccessful(false); // 用于设置运行结果的成功或失败,如果是"false"则表示结果失败,否则则表示成功  
	            return;  
	        } finally {  
	            try {  
	                if (rs != null)  
	                    rs.close();  
	            } catch (SQLException e) {  
	            }  
	            try {  
	                if (stm != null)  
	                    stm.close();  
	            } catch (SQLException e) {  
	            }             
	            try {  
	                if (conn != null)  
	                    conn.close();  
	            } catch (SQLException e) {  
	            }  
	        }  
	        results.setSuccessful(true); 
	    }  
	 
	      
	    public static String rs2Str(ResultSet rs) {  
	        StringBuilder sb = new StringBuilder();  
	  
	        try {  
	            ResultSetMetaData rsmd = rs.getMetaData();  
	            int c = rsmd.getColumnCount();  
	            while (rs.next()) {  
	                sb.append("----------------------------------------------------------").append("\\r\\n");;  
	                for (int i = 0; i < c; i++) {  
	                    sb.append(rsmd.getColumnLabel(i + 1)).append("=").append(rs.getObject(i + 1)).append("\\r\\n");  
	                }  
	                sb.append("\\r\\n");  
	            }  
	        } catch (SQLException e) {  
	            e.printStackTrace();  
	        }  
	        return sb.toString();  
	    } 	   
	   
}

  说明:

该类继承ApacheJMeter_java.jar包中的AbstractJavaSamplerClient类,引用它就可以调用了。在继承AbstractJavaSamplerClient类的时候,我们需要实现4个方法:

setupTest():初始化方法,用于初始化性能测试时的每个线程,实际运行时每个线程仅执行一次
getDefaultParameters():用于设置传入的参数,可以设置多个,已设置的参数会显示到Jmeter参数列表中
runTest():性能测试时的线程运行体,即测试执行的循环体,根据线程数和循环次数的不同可执行多次
teardownTest():测试结束方法,用于结束性能测试中的每个线程,实际运行时,每个线程仅执行一次,在测试方法运行结束后执行

(2)打包:export -- jar file --选择打包内容和位置-- finsh

(3)将jar包放在Jmeter安装目录\\lib\\ext

(4)运行Jmeter,添加一个线程组(Thread Group),然后在该线程组下面添加一个Java Request(在Sampler中),在Java请求的类名称中选择咱们刚创建的类"JDBC.ImpalaJDBCJmeter",在下面参数列表的"arg1"后面输入要测试的字符串,然后添加一个监听器(view Restults Tree和Aggregate Report),设置一下模拟的用户数就可以测试了。如果测试不成功,Jmeter会在它自己个输出框中抛出这个字符串。

三, Jmeter知识讲解

  

  线程组的设置页面,默认设置1个线程,1秒启动,循环1次。线程数表示启动多少个线程,Ramp-Up Period表示花多长时间启动所有线程,循环次数表示每个线程的执行次数,例如,我设置线程数10,Ramp-Up Period为10,循环次数2,表示软件将在10秒内启动10个线程,也就是1秒启动1个线程,每个线程执行两次请求。

  此外,我们还可以勾选“调度器”,比如我填入持续时间100,启动延迟0,将循环次数勾选“永远”,表示线程立即启动,执行100秒后停止。

  监听器:

  • 图形结果以图形的形式显示吞吐量、偏移、平均值等信息。
  • 表格结果显示每一次请求的时间,返回,发送字节数,连接时间等等。
  • 聚合报告里面显示总体请求的吞吐量,错误率等等。

表格结果中显示了3个impala JDBC请求,分别由3个线程执行,每个线程执行1次,正好符合我们对于线程组的设置。图中每一列的含义分别表示请求序号,开始时间,线程序号(未实现),请求名,请求所花的时间,请求状态,请求字节数,发送字节数,等待时长,连接时间。

聚合报告如图所示,每一列的含义分别表示请求名称,请求总数,请求的平均响应时间(毫秒),50%的请求的响应时间,90%的请求的响应时间,95%的请求的响应时间,99%的请求的响应时间,最小的响应时间,最大的响应时间,错误的请求率(错误请求数/总的请求数),吞吐量(每秒处理的请求数),接收的字节速率,发送的字节速率。

 

参考:1. https://www.yiibai.com/jmeter/jmeter-database-test-plan.html

           2. 使用 Apache Jmeter进行NTLM和 Kerberos 认证:https://www.2cto.com/kf/201702/599720.html

以上是关于Jmeter jdbc接口测试的主要内容,如果未能解决你的问题,请参考以下文章

Jmeter的JDBC Request接口测试

JMeter接口测试-Include控制器

Jmeter测试数据库

接口测试很难吗?学会JMeter+Ant接口自动化搭建及实践

Jmeter JDBC的使用

jmeter进行的接口测试和压力测试