手寫java性能測試框架第二版
引言
依照領導要求區(qū)分了兩種壓測模式:固定次數(shù)壓測和固定時間壓測。此前一直沿用的都是固定次數(shù),所以本次第二版剝離了固定次數(shù)的模式增加了固定時間的模式。
這是第一版:性能測試框架
第二版的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 { /** * 計數(shù)鎖 * <p> * 會在concurrent類里面根據(jù)線程數(shù)自動設定 * </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; } }
固定次數(shù)模式的壓測虛擬類
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; /** * 請求時間限制的多線程類,限制每個線程執(zhí)行的次數(shù) * * <p> * 通常在測試某項用例固定時間的場景下使用,可以提前終止測試用例 * </p> * * @param <T> 閉包參數(shù)傳遞使用,Groovy腳本會有一些兼容問題,部分對象需要tostring獲取參數(shù)值 */ public abstract class ThreadLimitTimes<T> extends ThreadBase { private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTimes.class); /** * 任務請求執(zhí)行次數(shù) */ 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("執(zhí)行次數(shù):{},總耗時:{}", times, ee - ss); Concurrent.allTimes.addAll(t); } catch (Exception e) { logger.warn("執(zhí)行任務失敗!", 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; /** * 請求時間限制的多線程類,限制每個線程執(zhí)行的時間 * <p> * 通常在測試某項用例固定時間的場景下使用,可以提前終止測試用例 * </p> * * @param <T> 閉包參數(shù)傳遞使用,Groovy腳本會有一些兼容問題,部分對象需要tostring獲取參數(shù)值 */ public abstract class ThreadLimitTime<T> extends ThreadBase { /** * 全局的時間終止開關(guān) */ private static boolean key = false; private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTime.class); /** * 任務請求執(zhí)行時間,單位是秒 */ 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("執(zhí)行時間:{} s,總耗時:{}", time / 1000, ee - ss); Concurrent.allTimes.addAll(t); } catch (Exception e) { logger.warn("執(zhí)行任務失??!", e); } finally { if (countDownLatch != null) countDownLatch.countDown(); after(); } } /** * 用于在某些情況下提前終止測試 */ public static void stopAllThread() { key = true; } }
這里我多加了一個終止測試的key,暫時沒有用,以防萬一。之所以沒有采用另起線程去計時原因有二:進行測試過程中無論如何都會記錄時間戳,多余的計算比較時間戳大小消耗性能很低,可以忽略;另起線程設計麻煩,在發(fā)生意外情況時缺少第二種保險措施。
HTTPrequestbase為基礎的多線程類
下面是兩種實現(xiàn)類的Demo,以HTTPrequestbase作為基礎的多線程類。
固定次數(shù)模式的多線程類
/** * http請求多線程類 */ public class RequestThreadTimes extends ThreadLimitTimes { static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class); /** * 請求 */ public HttpRequestBase request; /** * 單請求多線程多次任務構(gòu)造方法 * * @param request 被執(zhí)行的請求 * @param times 每個線程運行的次數(shù) */ 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(); } /** * 多次執(zhí)行某個請求,但是不記錄日志,記錄方法用 loglong * <p>此方法只適應與單個請求的重復請求,對于有業(yè)務聯(lián)系的請求暫時不能適配</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("響應狀態(tài)碼:{},響應內(nèi)容:{}", 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; /** * 單請求多線程多次任務構(gòu)造方法 * * @param request 被執(zhí)行的請求 * @param times 每個線程運行的次數(shù) */ 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(); } /** * 多次執(zhí)行某個請求,但是不記錄日志,記錄方法用 loglong * <p>此方法只適應與單個請求的重復請求,對于有業(yè)務聯(lián)系的請求暫時不能適配</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("響應狀態(tài)碼:{},響應內(nèi)容:{}", content, response.getStatusLine()); response.close(); } }
其中可以發(fā)現(xiàn),差別就在于屬性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就不寫了,各位看官看著發(fā)揮即可,更多關(guān)于java性能測試框架的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java使用Rxtx實現(xiàn)串口通信調(diào)試工具
這篇文章主要為大家詳細介紹了java使用Rxtx實現(xiàn)簡單串口通信調(diào)試工具,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12Mybatis插入Oracle數(shù)據(jù)庫日期型數(shù)據(jù)過程解析
這篇文章主要介紹了Mybatis插入Oracle數(shù)據(jù)庫日期型數(shù)據(jù)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09詳解 問題:HttpServlet cannot be resolved to a type
這篇文章主要介紹了詳解 問題:HttpServlet cannot be resolved to a type的相關(guān)資料,需要的朋友可以參考下2017-03-03Windows中使用Java生成Excel文件并插入圖片的方法
這篇文章主要介紹了Windows中使用Java生成Excel文件并插入圖片的方法,其中向Excel中插入圖片文中通過使用Apache POI來實現(xiàn),需要的朋友可以參考下2016-02-02SpringCloud之@FeignClient()注解的使用方式
這篇文章主要介紹了SpringCloud之@FeignClient()注解的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09解決jasperreport導出的pdf每頁顯示的記錄太少問題
這篇文章主要介紹了解決jasperreport導出的pdf每頁顯示的記錄太少問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06