项目背景:
有3台机器:
远程数据库(192.168.125.130)
跳板机(192.168.125.129)
客户机(192.168.125.1),
客户机不能直接JDBC连接远程数据库,跳板机可以直接连接远程数据库。
解决策略:
客户机要想连接远程数据库只能通过SSH连接。
步骤1.在客户机,跳板机,远程数据库分别安装SSH
步骤2.在客户机命令行输入 SSH –L 3308:192.168.125.130:3306 [email protected]
3308:在客户机开启的端口号
3306:远程数据库端口号
[email protected] 跳板机用户名和主机
步骤3.输入跳板机密码
至此,已成功建立SSH连接。(SSH端口原理请自行百度)
这只是思路,具体实现请往下看。
上面已经说到了思路,那好办了,让jmter先建立SSH,然后再通过jdbc来访问。
以下是本人想到的两种方案:
1) 写一个类似于JDBCconfigure的 SSH JDBC configure组件(因本人时间有限未进行尝试)
2) 通过java sample来实现SSH连接(本文所实现的方法)
1. 跳过新建java Sample的步骤(读者不会的可自行百度)
本次我们要用到的外部jar包
2. 新建一个项目
3. 编写SSHutil工具类
主要实现的方法
1) 创建session方法
2)连接SSH方法
3)关闭SSH方法
package com.jcraft.jsch;
import java.io.Serializable;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class SSHutil implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
private static JSch jsch ;
private static Session session;
public Session getSession() {
return session;
}
public void setSession(Session session) {
SSHutil.session = session;
}
public Session creatsession(String SSHhost, String SSHPort, String SSHUsername, String SSHPassword){
try{
jsch = new JSch();
session = jsch.getSession(SSHUsername, SSHhost, Integer.parseInt(SSHPort));
session.setPassword(SSHPassword);
session.setConfig("StrictHostKeyChecking", "no");
}
catch(Exception e){
e.printStackTrace();
}
return session;
}
public void ConnectSSH(String localport, String remotehost, String remoteport) throws JSchException{
session.connect();
session.setPortForwardingL(Integer.parseInt(localport), remotehost, Integer.parseInt(remoteport));
//System.out.println("localhost:" + assinged_port + " -> " + remotehost + ":" + remoteport);
//System.out.println("startsession:" + session);
}
public void CloseSSH(Session session){
System.out.println("Session:" + session);
if (session != null &&session.isConnected()){
session.disconnect();
}
}
}
4. 编写Net类(用于判断端口是否被占用)
package com.jcraft.jsch;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class NetUtil {
/***
* true:already in using false:not using
* @param port
*/
public static boolean isLoclePortUsing(int port){
boolean flag = true;
try {
flag = isPortUsing("127.0.0.1", port);
} catch (Exception e) {
}
return flag;
}
/***
* true:already in using false:not using
* @param host
* @param port
* @throws UnknownHostException
*/
public static boolean isPortUsing(String host,int port) throws UnknownHostException{
boolean flag = false;
InetAddress theAddress = InetAddress.getByName(host);
try {
Socket socket = new Socket(theAddress,port);
flag = true;
} catch (IOException e) {
}
return flag;
}
}
5. 编写startSSH类(完整代码请联系作者)
package com.startSSH;
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;
import com.jcraft.jsch.NetUtil;
import com.jcraft.jsch.SSHutil;
public class StartSSH extends AbstractJavaSamplerClient {
private static final Logger log = LoggerFactory.getLogger(StartSSH.class);
@Override
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult result = new SampleResult();
result.sampleStart();
SSHutil util = new SSHutil();
String localport = arg0.getParameter("localport");
String remotehost = arg0.getParameter("remotehost");
String remoteport = arg0.getParameter("remoteport");
String SSHhost = arg0.getParameter("SSHhost");
String SSHPort = arg0.getParameter("SSHPort");
String SSHUsername = arg0.getParameter("SSHUsername");
String SSHPassword = arg0.getParameter("SSHPassword");
util.creatsession(SSHhost, SSHPort, SSHUsername, SSHPassword);
if(! util.getSession().isConnected() && NetUtil.isLoclePortUsing(Integer.parseInt(localport)) == false){
try{
util.ConnectSSH(localport, remotehost, remoteport);
result.setResponseMessage("现在开始连接");
result.setSuccessful(true);
}
catch(Exception e){
e.printStackTrace();
log.error(e.getMessage());
result.setResponseMessage("出现异常");
result.setSuccessful(false);
}
}
else if(NetUtil.isLoclePortUsing(Integer.parseInt(localport)) == true && util.getSession().isConnected()){
result.setResponseMessage("连接已存在");
result.setSuccessful(true);
}
else{
result.setSuccessful(false);
}
return result;
}
@Override
public Arguments getDefaultParameters() {
// TODO Auto-generated method stub
Arguments params = new Arguments();
params.addArgument("localport", "localport");
params.addArgument("remotehost", "remotehost");
params.addArgument("remoteport", "remoteport");
params.addArgument("SSHhost", "SSHhost");
params.addArgument("SSHPort", "SSHport");
params.addArgument("SSHUsername", "SSHUsername");
params.addArgument("SSHPassword", "SSHPassword");
return params;
}
@Override
public void setupTest(JavaSamplerContext context) {
}
@Override
public void teardownTest(JavaSamplerContext context) {
}
public static void main(String[] args) {
// TODO Auto-generated method stub
StartSSH test = new StartSSH();
Arguments arg0 = test.getDefaultParameters();
JavaSamplerContext context = new JavaSamplerContext(arg0);
test.setupTest(context);
test.runTest(context);
test.teardownTest(context);
}
}
6. 编写closeSSH类(完整代码请联系作者)
package com.startSSH;
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 com.jcraft.jsch.NetUtil;
import com.jcraft.jsch.SSHutil;
import org.slf4j.*;
public class CloseSSH extends AbstractJavaSamplerClient {
private static final Logger log = LoggerFactory.getLogger(CloseSSH.class) ;
@Override
public Arguments getDefaultParameters() {
// TODO Auto-generated method stub
Arguments params = new Arguments();
params.addArgument("localport", "localport");
return params;
}
@Override
public void setupTest(JavaSamplerContext context) {
}
@Override
public void teardownTest(JavaSamplerContext context) {
}
@Override
public SampleResult runTest(JavaSamplerContext arg0) {
// TODO Auto-generated method stub
SampleResult result = new SampleResult();
SSHutil util = new SSHutil();
String localport = arg0.getParameter("localport");
try {
if(NetUtil.isLoclePortUsing(Integer.parseInt(localport)) == true){
util.CloseSSH(util.getSession());
result.setResponseMessage("session status: "+util.getSession().isConnected()+" 关闭成功");
result.setSuccessful(true);
}
else{
result.setResponseMessage("session status: "+util.getSession().isConnected()+" 无须关闭");
result.setSuccessful(true);
}
} catch (Exception e) {
e.printStackTrace();
result.setSuccessful(false);
log.error(e.getMessage());
result.setResponseMessage("关闭失败"+"session: "+util.getSession());
}
return result;
}
public static void main(String[] args) {
CloseSSH test = new CloseSSH();
Arguments arg0 = test.getDefaultParameters();
JavaSamplerContext context = new JavaSamplerContext(arg0);
test.setupTest(context);
test.runTest(context);
test.teardownTest(context);
}
}
7. 把编写好的类分别打成两个jar包(StartSSH.jar,CloseSSH.jar)
8. 把打好的两个jar放到%JMTER_HOME%/lib/ext下
9. 打开JMeter,新建两个java request
10. 开始测试
成功,打完收工。
自此完成jmter通过SSH连接数据库功能。