10

今天写了一个可以测试并发数和运行次数的压力测试代码。(Java) - dawa大娃bigbaby

 3 years ago
source link: https://www.cnblogs.com/dawabigbaby/p/16136273.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

今天写了一个可以测试并发数和运行次数的压力测试代码#

  1. 介绍一下为什么会写这么一个工具。
  2. 介绍一个这个工具怎么用的。

背景#

最近在开发CoapServer端,以及模拟设备侧发送数据调用开发好的CoapServer的性能,进行压力测试。

自己没有找到合适的压力测试的工具,但是测试诉求相对比较简单,觉得用Java可以来控制测试。
测试维度:

  1. 一共模拟1W台设备,共计发送数据100W次
  2. 模拟多台设备同时发送数据。

代码和使用#

import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.Utils;
import org.eclipse.californium.elements.exception.ConnectorException;

import java.io.IOException;
import java.text.NumberFormat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PressTestClient {

    static int count = 0;
    //总访问量是client_num,并发量是thread_num
    int thread_num = 10;
    int client_num = 1000;

    float avg_exec_time = 0;
    float sum_exec_time = 0;
    long first_exec_time = Long.MAX_VALUE;
    long last_done_time = Long.MIN_VALUE;
    float total_exec_time = 0;

    String url = "";
    String postData = "";

    public PressTestClient(int thread_num, int client_num, String url, String postData) {

        this.thread_num = thread_num;
        this.client_num = client_num;
        this.url = url;
        this.postData = postData;
    }


    public void run() {

        final PressTestClient currentObj = this;

        final ConcurrentHashMap<Integer, ClientThreadRecord> records = new ConcurrentHashMap<Integer, ClientThreadRecord>();

        // 建立ExecutorService线程池
        ExecutorService exec = Executors.newFixedThreadPool(thread_num);
        // thread_num个线程可以同时访问
        // 模拟client_num个客户端访问
        final CountDownLatch doneSignal = new CountDownLatch(client_num);

        for (int i = 0; i < client_num; i++) {

            Runnable run = new Runnable() {

                public void run() {

                    int index = getIndex();
                    long st = System.currentTimeMillis();

                    try {
                        //测试的逻辑代码
                        TlsCoAPClient example = new TlsCoAPClient();
                        CoapClient coapClient = example.getClient("device_service");
                        CoapResponse response = null;
                        try {
                            System.out.println("start client request:" +index );
                            response = coapClient.get();
                            System.out.println("device_service: " + Utils.prettyPrint(response));
                            Thread.sleep(100);
                        } catch (ConnectorException | IOException e) {
                            e.printStackTrace();
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    records.put(index, new ClientThreadRecord(st, System.currentTimeMillis()));
                    doneSignal.countDown();//每调用一次countDown()方法,计数器减1
                }
            };
            exec.execute(run);
        }

        try {
            //计数器大于0 时,await()方法会阻塞程序继续执行
            doneSignal.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /**
         * 获取每个线程的开始时间和结束时间
         */
        for (int i : records.keySet()) {
            ClientThreadRecord r = records.get(i);
            sum_exec_time += ((double) (r.et - r.st)) / 1000;

            if (r.st < first_exec_time) {
                first_exec_time = r.st;
            }
            if (r.et > last_done_time) {
                this.last_done_time = r.et;
            }
        }

        this.avg_exec_time = this.sum_exec_time / records.size();
        this.total_exec_time = ((float) (this.last_done_time - this.first_exec_time)) / 1000;
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(4);


        System.out.println("======================================================");
        System.out.println("Thread Num: " + thread_num + ", Client Count: " + client_num + ".");
        System.out.println("Avg Exec Time:   " + nf.format(this.avg_exec_time) + " s");
        System.out.println("Total Exec Time: " + nf.format(this.total_exec_time) + " s");
        System.out.println("Throughput:      " + nf.format(this.client_num / this.total_exec_time) + " /s");
    }

    public static int getIndex() {
        return ++count;
    }

    public static void main(String[] args) {
        //总访问量和并发量两重循环,依次增大访问
        //访问量
        for (int j = 500; j < 501; j += 100) {
            //并发量
            for (int i = 500; i < 501; i += 1) {
                //要测试的URL
                String url = "http://www.baidu.com/";
                new PressTestClient(i, j, url, "").run();
            }
        }
        System.out.println("finished!");
    }
}

class ClientThreadRecord {
    long st;
    long et;

    public ClientThreadRecord(long st, long et) {
        this.st = st;
        this.et = et;
    }
}

如何使用?

  1. main方法中的循环此时是控制 运行数和并发数的
  2. 上面run方法,是控制你要测试的代码的。可以自定义。

效果展示#

运行图

运行图


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK