Operations 8 min read

How to Build a Real‑World API Load Test for a Knowledge‑Base Service

This article walks through the design, scenario planning, and Java implementation of a fixed‑thread load test that simulates teacher login, knowledge‑point queries, course recommendations, and collect/uncollect actions, then presents the resulting performance metrics.

FunTester
FunTester
FunTester
How to Build a Real‑World API Load Test for a Knowledge‑Base Service

About the "Link" Concept

The term "link" is used instead of "path" to describe a sequence of UI‑driven operations that differ from pure interface testing; it serves as a reference model based on UI and product‑thinking documentation.

Collaboration Requirements

Front‑end testers need to supplement business details, while operations staff provide request‑volume ratios, which were initially estimated intuitively.

Scenario and Test Design

The test simulates a teacher logging in, retrieving a knowledge‑point list, filtering recommended courses, performing collect and un‑collect actions, and finally fetching the teacher's own course list (including originals and collections).

A fixed‑thread model is used, targeting roughly 200 concurrent threads with a backup pool of 600 virtual users; each thread represents one user and repeatedly executes a "Q" cycle.

One Q cycle consists of nine HTTP requests (no socket calls), including three modification operations and six query operations.

Implementation Details

The core logic is implemented in a static helper class and a supplementary K class that stores knowledge‑point attributes (id, type, level) for easy reuse. All API calls use primitive types and String parameters.

package com.okayqa.composer.performance.resource1_4;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.funtester.base.bean.AbstractBean;
import com.funtester.base.constaint.ThreadLimitTimesCount;
import com.funtester.frame.execute.Concurrent;
import com.funtester.httpclient.ClientManage;
import com.funtester.utils.ArgsUtil;
import com.okayqa.composer.base.OkayBase;
import com.okayqa.composer.function.Mirro;
import com.okayqa.composer.function.OKClass;

class Login_collect_uncollect extends OkayBase {
    public static void main(String[] args) {
        ClientManage.init(10, 5, 0, "", 0);
        def util = new ArgsUtil(args);
        def thread = util.getIntOrdefault(0, 30);
        def times = util.getIntOrdefault(1, 40);
        def tasks = [];
        thread.times { tasks << new FunTester(it, times) }
        new Concurrent(tasks, "资源库1.4登录>查询>收藏>取消收藏链路压测").start();
        allOver();
    }
    // ... (inner classes FunTester and K omitted for brevity) 
}

The supporting AbstractBean class provides JSON conversion, file saving, console printing, and cloning utilities for bean objects.

package com.funtester.base.bean;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.funtester.frame.Save;
import com.funtester.frame.SourceCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

abstract class AbstractBean {
    static final Logger logger = LoggerFactory.getLogger(AbstractBean.class);
    JSONObject toJson() { return JSONObject.parseObject(JSONObject.toJSONString(this)); }
    def save() { Save.saveJson(this.toJson(), this.getClass().toString() + SourceCode.getMark()); }
    def print() { logger.warn(this.getClass().toString() + ":" + this.toString()); }
    def initFrom(String str) { JSONObject.parseObject(str, this.getClass()); }
    def initFrom(Object obj) { initFrom(JSON.toJSONString(obj)); }
    def copyFrom(AbstractBean source) { BeanUtils.copyProperties(source, this); }
    def copyTo(AbstractBean target) { BeanUtils.copyProperties(this, target); }
    @Override String toString() { return JSONObject.toJSONString(this); }
    @Override protected Object clone() { initFrom(this); }
}

Test Results

{
  "rt":1665,
  "total":1188,
  "qps":18.018,
  "failRate":0.0,
  "threads":30,
  "startTime":"2021-02-24 16:57:23",
  "endTime":"2021-02-24 16:58:34",
  "errorRate":1.01,
  "executeTotal":1188,
  "mark":"资源库1.4登录>查询>收藏>取消收藏链路压测241657",
  "table":"eJzj5VLAD15sbXm2a8LTXZMN9Uyez9z9dO9Uu2fzl75Yv8ju2ZRtL6b32z3tn/..."
}

The JSON output shows a response time of 1665 ms, 30 threads, a QPS of 18.018, and an error rate of 1.01 % for 1,188 total requests.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaOperationsPerformance TestingLoad TestingAPI testing
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.