首页 > 编程语言 >java的cmd命令行和jsch执行压测

java的cmd命令行和jsch执行压测

时间:2023-07-15 23:32:00浏览次数:47  
标签:jsch count java 8082 压测 TestController api com

前言

项目中用到了cmd命令去执行,但是发现一个问题就是,当需要切换用户和执行命令的时候特别的麻烦,所以后面又该用了jsch的连接方式,测试一下性能理想不理想,看看有劣势。

相关配置

ssh的连接数

# cat /etc/ssh/sshd_config | grep MaxSessions

#MaxSessions 1000

测试代码

@GetMapping("/cmd")
public String testCmd(@RequestParam Integer count) {
    log.info(" id = {}", count);
    ExecutorService executorService = Executors.newFixedThreadPool(count);
    long start = System.nanoTime();
    CountDownLatch latch = new CountDownLatch(count);
    for (int i = 0; i < count; i++) {
        executorService.execute(()->{
            try {
                String command = "sleep 3 && echo 'Done waiting!' "; // 替换成您要运行的CMD命令
                //                    Process process = Runtime.getRuntime().exec(command);
                // 创建ProcessBuilder对象,设置要执行的命令
                ProcessBuilder pb = new ProcessBuilder("sleep", "10");

                // 启动进程
                Process process = pb.start();
                InputStream inputStream = process.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    log.info("data:{}", line);
                }
                reader.close();
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
    try {
        latch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    long end = System.nanoTime();
    long offset = TimeUnit.NANOSECONDS.toMillis(end - start);
    log.info("cost time = {} ms", offset);
    return "hello: " + offset;
}

@GetMapping("/ssh")
public String testSsh(@RequestParam Integer count) {
    log.info(" id = {}", count);
    ExecutorService executorService = Executors.newFixedThreadPool(count);
    long start = System.nanoTime();
    CountDownLatch latch = new CountDownLatch(count);
    for (int i = 0; i < count; i++) {
        executorService.execute(()->{
            try {
                cmdCreateFileDirectory(" sleep 10 && echo 'Done waiting!'", "steven",
                                       "admin");
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
    try {
        latch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    long end = System.nanoTime();
    long offset = TimeUnit.NANOSECONDS.toMillis(end - start);
    log.info("cost time = {} ms", offset);
    return "hello: " + offset;
}


// write a create file directory function
public void cmdCreateFileDirectory(final String command, final String serverUser,
                                   final String serverPassword) {
    int exitValue = 0;
    long startTime = System.currentTimeMillis();
    final StringBuilder result = new StringBuilder();
    try {
        JSch jsch = new JSch();
        Session session = jsch.getSession(serverUser, "127.0.0.1", 22);
        session.setPassword(serverPassword);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect(10000);

        Channel channel = session.openChannel("exec");
        ((ChannelExec) channel).setCommand(command);
        channel.setInputStream(null);
        ((ChannelExec) channel).setErrStream(System.err);

        InputStream in = channel.getInputStream();
        channel.connect();
        byte[] tmp = new byte[1024];
        while (true) {
        while (in.available() > 0) {
        int i = in.read(tmp, 0, 1024);
        if (i < 0) break;
        result.append(new String(tmp, 0, i));
        }
        if (channel.isClosed()) {
        if (in.available() > 0) continue;
        exitValue = channel.getExitStatus();
        log.debug("exit-status: {}", exitValue);
        break;
        }
        try {
        Thread.sleep(10);
        } catch (Exception ee) {
        }
        }
        channel.disconnect();
        session.disconnect();
        if (exitValue != 0) {
        log.error("create file directory error: " + exitValue + " " + command);
        }
        log.info(" create file directory success, command: {}, content:{} total cost time:{}", command,
        result.toString(), System.currentTimeMillis() - startTime);
        } catch (JSchException e) {
        log.error(e.getMessage(), e);
        } catch (IOException e) {
        log.error(e.getMessage(), e);
        }
        }

测试cmd

java的cmd命令行和jsch执行压测_java

CPU还算稳定,刚开始120%后面50%,然后30%,然后50%这样波动

程序日志

2023-07-12 17:12:18.643 INFO 6466 --- [nio-8082-exec-1] com.example.demotest.api.TestController : id = 1000

2023-07-12 17:12:32.385 INFO 6466 --- [nio-8082-exec-1] com.example.demotest.api.TestController : cost time = 13739 ms

2023-07-12 17:13:04.250 INFO 6466 --- [nio-8082-exec-2] com.example.demotest.api.TestController : id = 1000

2023-07-12 17:13:17.461 INFO 6466 --- [nio-8082-exec-2] com.example.demotest.api.TestController : cost time = 13210 ms

2023-07-12 17:13:42.428 INFO 6466 --- [nio-8082-exec-3] com.example.demotest.api.TestController : id = 1000

2023-07-12 17:13:55.645 INFO 6466 --- [nio-8082-exec-3] com.example.demotest.api.TestController : cost time = 13216 ms

2023-07-12 17:14:04.956 INFO 6466 --- [nio-8082-exec-4] com.example.demotest.api.TestController : id = 1000

2023-07-12 17:14:17.633 INFO 6466 --- [nio-8082-exec-4] com.example.demotest.api.TestController : cost time = 12676 ms

平均执行时间在13s左右

测试ssh

java的cmd命令行和jsch执行压测_System_02

cpu在240~100之间徘徊

2023-07-12 17:18:10.288 INFO 6466 --- [nio-8082-exec-5] com.example.demotest.api.TestController : cost time = 30565 ms

2023-07-12 17:19:59.174 INFO 6466 --- [nio-8082-exec-9] com.example.demotest.api.TestController : cost time = 35478 ms


介于ssh连接的原因,还是会有很多连接不上ssh,当IO操作不频繁有一部分可能会导致CPU变高,因为线程数很多。

com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset

at com.jcraft.jsch.Session.connect(Session.java:565) ~[jsch-0.1.55.jar!/:na]

at com.example.demotest.api.TestController.cmdCreateFileDirectory(TestController.java:113) ~[classes!/:0.0.1-SNAPSHOT]

at com.example.demotest.api.TestController.lambda$testSsh$1(TestController.java:82) ~[classes!/:0.0.1-SNAPSHOT]

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]

at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]


2023-07-12 18:08:47.839 ERROR 6466 --- [l-50-thread-136] com.example.demotest.api.TestController : Session.connect: java.net.SocketException: Connection reset


com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset

at com.jcraft.jsch.Session.connect(Session.java:565) ~[jsch-0.1.55.jar!/:na]

at com.example.demotest.api.TestController.cmdCreateFileDirectory(TestController.java:113) ~[classes!/:0.0.1-SNAPSHOT]

at com.example.demotest.api.TestController.lambda$testSsh$1(TestController.java:82) ~[classes!/:0.0.1-SNAPSHOT]

100条以内执行统计

# cat /etc/ssh/sshd_config | grep MaxSessions

#MaxSessions 10

改成请求100

cpu

ssh30~4%. cmd无影响

执行耗时单位ms

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/ssh?count=10

hello: 10430

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/ssh?count=10

hello: 10356

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/ssh?count=10

hello: 10502

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/cmd?count=10

hello: 10017

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/cmd?count=10

hello: 10023

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/cmd?count=10

hello: 10018

改成500

cpu消耗

cmd: 50~10% ssh: 200~30%

耗时消耗ms

[root@dev-base-01 ~]# curl http://localhost:8082/api/test/cmd?count=1000

hello: 14946[root@dev-base-01 ~]# curl http://localhost:8082/api/test/cmd?count=500

hello: 12318[root@dev-base-01 ~]# curl http://localhost:8082/api/test/cmd?count=500

hello: 11037[root@dev-curl http://localhost:8082/api/test/ssh?count=500

^[[Ahello: 20826[root@dev-base-01 ~]# curl http://localhost:8082/api/test/ssh?count=500

hello: 22675[root@dev-base-01 ~]# curl http://localhost:8082/api/test/ssh?count=500

hello: 22629[root@dev-base-01 ~]#

总结

从测试结果来看cmd的执行耗时cpu明显要低很多而且耗时也低很多,但是明明cmd创建了一个进程去执行命令,所以但从表面数据来看是好像明显cmd更加的明显,但是从代码维护和后续更多功能开发又觉得cmd有点像一个附加功能,不是主要的做命令执行的,SSH之类的脚本还是需要连接工具去执行,也搜索到类似的文章,也看过类似的书籍,都讨论JAVA命令行的缺点,之前一个是内存溢出,后面一个案例是重构很难适应新业务。

一般来说,使用第三方库连接SSH执行脚本的性能更好。因为第三方库连接SSH可以直接在Java代码中执行远程命令,而不需要像底层调用exec一样需要创建进程、执行命令、等待命令执行完成等操作,从而可以更加高效地执行远程命令。但具体的性能情况还需要根据具体的实现方式和场景来进行评估。

引用

SSH Connection With Java | Baeldung

JSch- Java Secure Channel - Examples

JavaJSchExample to run Shell Commands on SSH Unix Server | DigitalOcean








标签:jsch,count,java,8082,压测,TestController,api,com
From: https://blog.51cto.com/stevenchendy/6734206

相关文章

  • Java数组
    0x01认识数组1、什么是数组数组就是用来存储一批同种类型数据的容器。int[]arr={20,10,80,60,90};String[]names={"张三","李四","王二"};2、为什么要用数组假如用变量学生名字,然后完成随机点名功能,怎么实现?存在有什么问题?Stringname1="张誉";Stringnam......
  • java写入数据 加锁操作
    publicstaticvoidmain(Stringargs[]){ ConnectionconnMySQL=null; Statementstmt=null; StringstrJDBC_DRIVER="com.mysql.cj.jdbc.Driver";//java8的链接写法,java5把cj.去掉就行StringstrDB_URL="jdbc:mysql://localhost:3306......
  • JavaScript
    html<!DOCTYPEhtml><htmllang="en"xmlns="http://www.w3.org/1999/html"><head><metaname="author"content="weiyupeng"><metaname="time"content="2023/7/1020:23"......
  • java-base-two
    ArrayList扩容机制扩容一半(默认方式):当容量不足时,ArrayList将容量扩大为原来的1.5倍,即将原来的容量除以2,然后加上原来的容量。       如果新创建的集合有带初始值,默认就是传入的大小,在初始化时就会用传入的大小不会扩容,当大小不够后再去扩容。在方法中定义......
  • 吊打面试官的16000字JVM专属秘籍,又一个Java面试神器!
    前言吊打面试官的16000字JVM专属秘籍,总共包含三部分的内容,从基础到进阶带大家一步步深入理解JVM!学完就可以在简历上面直接写上精通JVM!因为篇幅限制这里只给大家做简单的一个介绍,也就是进行一个大点的梳理,每个大点下面又有很多细枝末节的技能知识需要大家好好学透,并且能够掌握吸收到......
  • Java 集合和流
    (目录)一、从集合中获取流JavaStreamAPI提供了一种更实用的编程方法来迭代和处理集合等元素。JavaStreamAPI是在Java8中添加到Java中的。流大部分是和Javalambda表达式一起使用,不熟悉lambda表达式的建议了解之后阅读。可以通过调用给定集合的方法从集合中获取流......
  • Java学习day04: 方法和数组
    我在B站上大学......
  • Java重要类型的转换
    类型转换由于Java是强类型语言,所以要进行有些运算的时候的,需要用到类型转换。低--------------------------------------------------------->高byte,short,char--->int-->long-->float-->double运算中,不同类型的数据先转化为同一类型,然后进行运算。 ......
  • JavaDoc生成文档
    JavaDoc生成文档javados命令是用来生成自己API文档的参数信息:@author作者名@version版本号@since指明需要最早使用的jdk版本@param参数名@return返回值情况@throws异常抛出情况利用命令行窗口生成API文档:右击Doc----->点击OpenInExplorer找到文档所......
  • 学习java第3天
    计算机语言发展史第一代语言机器语言:二进制第二代语言汇编语言应有:逆向工程机器人病毒第三代语言摩尔定律高级语言:c语言c++语言Java语言c#语言·······Java的诞生1972年c诞生贴近硬件,运行快,效率高操作系统,编辑器,数据库1982年c++诞生面向对象,......