How to Build a Distributed Performance Testing Framework with DCS_FunTester and Docker
This article details a practical implementation of a distributed performance testing framework using DCS_FunTester, describing the master‑slave architecture, Docker image setup, Groovy/Java scripts, sample code, console output, and server logs to help engineers replicate the approach.
Architecture Overview
The article documents a hands‑on extension of the DCS_FunTester framework to enable distributed performance testing. The system consists of three components: a master scheduler that receives test cases and distributes tasks, one or more slave test nodes that execute the received scripts, and the server under test that provides the testing API.
Master Scheduler
The master node receives a test case, packages the Groovy or Java script, and uploads it to the slave nodes for execution. For this proof‑of‑concept only a single slave node is used, and a fixed‑thread, fixed‑request‑count load model is applied.
Master Script
package com.mocofun.moco.main
import com.alibaba.fastjson.JSONObject
import com.funtester.base.bean.Result
import com.funtester.utils.RWUtil
import com.mocofun.moco.MocoServer
class DcsServer3 extends MocoServer {
public static void main(String[] args) {
def server = getServer(12345)
def res = new JSONObject()
res.script = RWUtil.readTxtByString("/Users/oker/IdeaProjects/funtester/src/test/groovy/com/funtest/groovytest/Share.groovy")
server.get(urlStartsWith("/m")).response(obRes(Result.success(res)))
def run = run(server)
waitForKey("fun")
run.stop()
}
}Test Case
package com.funtest.groovytest
import com.funtester.config.Constant
import com.funtester.frame.execute.Concurrent
import com.funtester.frame.thread.RequestThreadTimes
import com.funtester.httpclient.ClientManage
import com.funtester.httpclient.FunLibrary
import com.funtester.utils.ArgsUtil
import org.apache.http.client.methods.HttpGet
class Share extends FunLibrary {
public static void main(String[] args) {
ClientManage.init(10, 5, 0, "", 0);
def util = new ArgsUtil(args)
int thread = util.getIntOrdefault(0, 20);
int times = util.getIntOrdefault(1, 100);
String url = "http://localhost:12345/m";
HttpGet get = getHttpGet(url);
Constant.RUNUP_TIME = 0;
RequestThreadTimes task = new RequestThreadTimes(get, times);
new Concurrent(task, thread, "Local Fixed QPS Test").start();
}
public static void test(String params) {
main(params.split(COMMA))
}
}Slave Test Node
package com.funtest.groovytest
import com.funtester.frame.execute.ExecuteGroovy
import com.funtester.httpclient.FunLibrary
class Dcs3 extends FunLibrary {
public static void main(String[] args) {
while (true) {
String url = "http://localhost:12345/m"
def get = getHttpGet(url)
def response = getHttpResponse(get)
if (response.getInteger("code") == 0) {
def data = response.getJSONObject("data")
def script = data.getString("script")
ExecuteGroovy.executeScript(script)
}
sleep(5.0)
fail()
}
}
}Console Output
INFO-> 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> 请求uri:http://localhost:12345/m , 耗时:463 ms , HTTPcode: 200
INFO-> =========预热完成,开始测试!=========
INFO-> 本地固定QPS测试进度:▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍▍ 100%
INFO-> 总计20个线程,共用时:0.754 s,执行总数:1933,错误数:0,失败数:0
INFO-> 数据保存成功!文件名:/Users/oker/IdeaProjects/funtester/long/data/本地固定QPS测试251800_20Performance Result
Server Log
Content-Length: 1089
Content-Type: text/plain; charset=utf-8
{"code":0,"data":{"script":"package com.funtest.groovytest;
import com.funtester.config.Constant;
import com.funtester.frame.execute.Concurrent;
import com.funtester.frame.thread.RequestThreadTimes;
import com.funtester.httpclient.ClientManage;
import com.funtester.httpclient.FunLibrary;
import com.funtester.utils.ArgsUtil;
import org.apache.http.client.methods.HttpGet;
class Share extends FunLibrary {
public static void main(String[] args) {
ClientManage.init(10, 5, 0, \"\", 0);
def util = new ArgsUtil(args)
int thread = util.getIntOrdefault(0, 20);
int times = util.getIntOrdefault(1, 100);
String url = \"http://localhost:12345/m\";
HttpGet get = getHttpGet(url);
Constant.RUNUP_TIME = 0;
RequestThreadTimes task = new RequestThreadTimes(get, times);
new Concurrent(task, thread, \"Local Fixed QPS Test\").start();
}
public static void test(String params) {
main(params.split(COMMA))
}
}
"}}
Request received:
GET /favicon.ico HTTP/1.1
Host: localhost:12345
Connection: keep-alive
... (truncated)
Response return:
HTTP/1.1 400The article concludes that the single‑node version of the distributed framework is still in internal testing, and readers are invited to follow future updates via the author’s public account.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
