引言

依照领导要求区分了两种压测模式:固定次数压测和固定时间压测。此前一直沿用的都是固定次数,所以本次第二版剥离了固定次数的模式增加了固定时间的模式。

这是第一版:性能测试框架

第二版的threadbase代码如下

package com.fun.base.constaint;
import com.fun.frame.SourceCode;
import java.util.concurrent.CountDownLatch;
/**
 * 多线程任务基类,可单独使用
 */
public abstract class ThreadBase<T> extends SourceCode implements Runnable {
    /**
     * 计数锁
     * <p>
     * 会在concurrent类里面根据线程数自动设定
     * </p>
     */
    CountDownLatch countDownLatch;
    /**
     * 用于设置访问资源
     */
    public T t;
    protected ThreadBase() {
        super();
    }
    /**
     * groovy无法直接访问t,所以写了这个方法
     *
     * @return
     */
    public String getT() {
        return t.toString();
    }
    /**
     * 运行待测方法的之前的准备
     */
    protected abstract void before();
    /**
     * 待测方法
     *
     * @throws Exception
     */
    protected abstract void doing() throws Exception;
    /**
     * 运行待测方法后的处理
     */
    protected abstract void after();
    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
}

固定次数模式的压测虚拟类

package com.fun.base.constaint;
import com.fun.frame.excute.Concurrent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import static com.fun.utils.Time.getTimeStamp;
/**
 * 请求时间限制的多线程类,限制每个线程执行的次数
 *
 * <p>
 * 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例
 * </p>
 *
 * @param <T> 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值
 */
public abstract class ThreadLimitTimes<T> extends ThreadBase {
    private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTimes.class);
    /**
     * 任务请求执行次数
     */
    public int times;
    /**
     * 用于设置访问资源
     */
    public T t;
    public ThreadLimitTimes(T t, int times) {
        this(times);
        this.t = t;
    }
    public ThreadLimitTimes(int times) {
        this();
        this.times = times;
    }
    protected ThreadLimitTimes() {
        super();
    }
    /**
     * groovy无法直接访问t,所以写了这个方法
     *
     * @return
     */
    public String getT() {
        return t.toString();
    }
    @Override
    public void run() {
        try {
            before();
            List<Long> t = new ArrayList<>();
            long ss = getTimeStamp();
            for (int i = 0; i < times; i  ) {
                long s = getTimeStamp();
                doing();
                long e = getTimeStamp();
                t.add(e - s);
            }
            long ee = getTimeStamp();
            logger.info("执行次数:{},总耗时:{}", times, ee - ss);
            Concurrent.allTimes.addAll(t);
        } catch (Exception e) {
            logger.warn("执行任务失败!", e);
        } finally {
            if (countDownLatch != null)
                countDownLatch.countDown();
            after();
        }
    }
    /**
     * 运行待测方法的之前的准备
     */
    protected abstract void before();
    /**
     * 待测方法
     *
     * @throws Exception
     */
    protected abstract void doing() throws Exception;
    /**
     * 运行待测方法后的处理
     */
    protected abstract void after();
}

固定时间模式虚拟类

package com.fun.base.constaint;
import com.fun.frame.excute.Concurrent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import static com.fun.utils.Time.getTimeStamp;
/**
 * 请求时间限制的多线程类,限制每个线程执行的时间
 * <p>
 * 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例
 * </p>
 *
 * @param <T> 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值
 */
public abstract class ThreadLimitTime<T> extends ThreadBase {
    /**
     * 全局的时间终止开关
     */
    private static boolean key = false;
    private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTime.class);
    /**
     * 任务请求执行时间,单位是秒
     */
    public int time;
    /**
     * 用于设置访问资源
     */
    public T t;
    public ThreadLimitTime(T t, int time) {
        this(time);
        this.t = t;
    }
    public ThreadLimitTime(int time) {
        this();
        this.time = time * 1000;
    }
    protected ThreadLimitTime() {
        super();
    }
    @Override
    public void run() {
        try {
            before();
            List<Long> t = new ArrayList<>();
            long ss = getTimeStamp();
            while (true) {
                long s = getTimeStamp();
                doing();
                long e = getTimeStamp();
                t.add(e - s);
                if ((e - ss) > time || key) break;
            }
            long ee = getTimeStamp();
            logger.info("执行时间:{} s,总耗时:{}", time / 1000, ee - ss);
            Concurrent.allTimes.addAll(t);
        } catch (Exception e) {
            logger.warn("执行任务失败!", e);
        } finally {
            if (countDownLatch != null)
                countDownLatch.countDown();
            after();
        }
    }
    /**
     * 用于在某些情况下提前终止测试
     */
    public static void stopAllThread() {
        key = true;
    }
}

这里我多加了一个终止测试的key,暂时没有用,以防万一。之所以没有采用另起线程去计时原因有二:进行测试过程中无论如何都会记录时间戳,多余的计算比较时间戳大小消耗性能很低,可以忽略;另起线程设计麻烦,在发生意外情况时缺少第二种保险措施。

HTTPrequestbase为基础的多线程类

下面是两种实现类的Demo,以HTTPrequestbase作为基础的多线程类。

固定次数模式的多线程类

/**
 * http请求多线程类
 */
public class RequestThreadTimes extends ThreadLimitTimes {
    static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class);
    /**
     * 请求
     */
    public HttpRequestBase request;
    /**
     * 单请求多线程多次任务构造方法
     *
     * @param request 被执行的请求
     * @param times   每个线程运行的次数
     */
    public RequestThreadTimes(HttpRequestBase request, int times) {
        this.request = request;
        this.times = times;
    }
    @Override
    public void before() {
        GCThread.starts();
    }
    @Override
    protected void doing() throws Exception {
        getResponse(request);
    }
    @Override
    protected void after() {
        GCThread.stop();
    }
    /**
     * 多次执行某个请求,但是不记录日志,记录方法用 loglong
     * <p>此方法只适应与单个请求的重复请求,对于有业务联系的请求暂时不能适配</p>
     *
     * @param request 请求
     * @throws IOException
     */
    void getResponse(HttpRequestBase request) throws IOException {
        CloseableHttpResponse response = ClientManage.httpsClient.execute(request);
        String content = FanLibrary.getContent(response);
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
            logger.warn("响应状态码:{},响应内容:{}", content, response.getStatusLine());
        response.close();
    }
}

固定时间模式的多线程类

package com.fun.frame.thead;
import com.fun.base.constaint.ThreadLimitTime;
import com.fun.frame.httpclient.ClientManage;
import com.fun.frame.httpclient.FanLibrary;
import com.fun.frame.httpclient.GCThread;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
 * http请求多线程类
 */
public class RequestThreadTime extends ThreadLimitTime {
    static Logger logger = LoggerFactory.getLogger(RequestThreadTime.class);
    /**
     * 请求
     */
    public HttpRequestBase request;
    /**
     * 单请求多线程多次任务构造方法
     *
     * @param request 被执行的请求
     * @param times   每个线程运行的次数
     */
    public RequestThreadTime(HttpRequestBase request, int time) {
        this.request = request;
        this.time = time;
    }
    @Override
    public void before() {
        GCThread.starts();
    }
    @Override
    protected void doing() throws Exception {
        getResponse(request);
    }
    @Override
    protected void after() {
        GCThread.stop();
    }
    /**
     * 多次执行某个请求,但是不记录日志,记录方法用 loglong
     * <p>此方法只适应与单个请求的重复请求,对于有业务联系的请求暂时不能适配</p>
     *
     * @param request 请求
     * @throws IOException
     */
    void getResponse(HttpRequestBase request) throws IOException {
        CloseableHttpResponse response = ClientManage.httpsClient.execute(request);
        String content = FanLibrary.getContent(response);
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
            logger.warn("响应状态码:{},响应内容:{}", content, response.getStatusLine());
        response.close();
    }
}

其中可以发现,差别就在于属性time还是times的设定。

使用Demo:

package com.fun;
import com.fun.base.constaint.ThreadLimitTime;
import com.fun.frame.SourceCode;
import com.fun.frame.excute.Concurrent;
import java.util.ArrayList;
import java.util.List;
public class AR extends SourceCode {
    public static void main(String[] args) {
        ThreadLimitTime<Object> threadLimitTime = new ThreadLimitTime<Object>(10) {
            /**
             * 运行待测方法的之前的准备
             */
            @Override
            protected void before() {
            }
            /**
             * 待测方法
             *
             * @throws Exception
             */
            @Override
            protected void doing() throws Exception {
                AR.test();
            }
            /**
             * 运行待测方法后的处理
             */
            @Override
            protected void after() {
            }
        };
        new Concurrent(threadLimitTime,5).start();
        FanLibrary.testOver();
    }
    public static void test() {
        synchronized (AR.class) {
            sleep(100);
            output("fun");
        }
    }
}

剩下的mysql和redis以及dubbo的Demo就不写了,各位看官看着发挥即可,更多关于java性能测试框架的资料请关注Devmax其它相关文章!

手写java性能测试框架第二版的更多相关文章

  1. xcode6.1 – Xcode 6.1中项目模板中缺少类前缀

    项目模板上曾经有一个类前缀字段,这有助于区分项目类和框架类.Xcode6.1项目模板中不再提供此功能.这背后的意图是什么?

  2. ios – 伞框架

    错误.应用程序,通常位于…错误仍然存在你也可以在这里添加(子)框架的路径.

  3. ios – UIView框架大小的问题

    我正在开发一个iPad项目,目前正在使用Landscape视图.我试着这样做:为什么这总是返回960?虽然在景观中,视图本身的高度尺寸应为768对吗?

  4. 安装自定义cocoa框架的最佳方法

    我有一个自定义框架,遵循Apple的框架编程指南>>中的建议.Installingyourframework我在/Library/Frameworks中安装.我通过使用以下脚本添加RunScript构建阶段来完成此操作:在我的项目中,我然后链接/Library/Frameworks/MyFramework并将其导入我的类中,如下所示:这非常有效,除了我总是在调试器控制台中看到以下消息:Loadin

  5. ios – 在设备上构建和运行时,仅将嵌入式框架与其他动态框架链接失败

    TL;博士将您的嵌入式框架与其他框架链接,并且不将其他框架与您的应用程序链接,导致Build&在设备上运行.描述:建立:我的设置非常简单(Swift2.3&XcodeXcode8.0;Build版本8S162m):>使用Carthage(0.17.2)我用xcodebuild8.0和TOOLCHAINS=com.apple.dt.toolchain.Swift_2_3carthagebui

  6. iOS 8嵌入式框架中的头文件

    我正在尝试创建一个用于iOS8的嵌入式框架.在创建一个名为SampleKit(BTW;这里有任何约定,我应该使用前缀吗?)之后,它包含一个令我困惑的头文件:我知道FOUNDATION_EXPORT是extern或extern“C”的宏,但我不确定这两个常量.我应该在哪里为他们设定价值?解决方法项目>构建设置>版本控制>当前项目版本:

  7. 在Monotouch上模拟.NET的框架?

    有没有人使用过他们发现与Monotouch兼容的.NET模拟框架?在尝试使用之前,我很好奇与NMock,NSubstitute,Moq和其他框架的兼容性.Xamarin刚刚加强了它的单元测试支持,但没有提到模拟框架.仅供参考,我希望在VS2010上为非UI位做很多开发,并在UI进入时移动到iOS平台.谢谢您的帮助.解决方法我建议只使用手动模拟:如果我不得不猜测RhinoMocks,Moq等大量使用Reflection.Emit(你怎么能做他们能做的疯狂?),这将无法在MonoTouch上使用AOT编译器运

  8. 在ios上使用来自框架的boost :: filesysystem路径

    我一直在使用Boost作为PeteGoodliffe脚本构建的框架已有一段时间了.效果很好.最近我遇到了一个问题,可以通过将以下代码放入另一个全新的XCode项目中的视图控制器的viewDidLoad中来重现:当路径对象被销毁时会导致EXC_BAD_ACCESS.有没有其他人遇到这个问题?

  9. ios – 在约束依赖于框架的自定义视图中使用自动布局

    我正在编写一个以编程方式初始化的自定义视图.我重写updateConstraints以添加此视图所需的所有约束.:问题是self.bounds返回CGRectZero的等价物.我做了我的研究并根据这个objc.ioarticle,这是预期的,因为在调用layoutSubviews之前框架不会被设置.它也提到了Toforcethesystemtoupdatethelayoutofaviewtreei

  10. ios – “禁用模块时使用’@import’”错误 – 启用模块和链接框架= YES

    我有一个使用CocoaPods并使用’SCLAlertView-Objective-C’窗格的项目.该pod使用@importUIKit;模块样式导入.我在目标和项目设置中将“启用模块(C&Objective-C)”和“自动链接框架”设置为YES.当模块被禁用时,我仍然得到“使用’@import’错误.有没有什么可以阻止Xcode能够启用模块,如使用.pch文件,任何链接器标志,或者我没有提到的任

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部