Design and Implementation of a Realistic Simulation Load‑Testing System for High‑Concurrency Scenarios
The article describes the background, architecture, tool selection, key features, implementation challenges (including Go code for TCP/WebSocket handling), and real‑world deployment of a distributed simulation load‑testing platform that supports dynamic QPS control, multi‑protocol testing, and end‑to‑end data verification.
1. Project Background Existing load‑testing tools focus on a single QPS metric and cannot accurately simulate each user as an independent TCP connection. To achieve realistic user behavior, the team built a simulation load‑testing system that models one user per TCP connection, supports dynamic QPS control, and validates data consistency across client, server, and database layers.
2. Formation of the Simulation Load‑Testing System
2.1 Tool Selection After comparing common tools, the team chose Locust as the framework because of its distributed nature, coroutine‑based concurrency, and extensibility. The request client uses fasthttp , a high‑performance Go HTTP library that reuses workers and offers up to ten‑fold speed improvements over net/http .
2.1.3 System Features
Distributed deployment
Fixed‑URL, parameterized, and WebSocket protocol testing
Support for UDP, HTTP/2, RTMP/HLS, MQTT, etc.
Direct pressure on Redis, Kafka, MySQL
Custom scripts for full‑link data reconciliation
Dynamic, controllable QPS and TCP connections
Second‑level start/stop with immediate result display
2.1.4 Implementation Challenges Simulating millions of users with persistent TCP/WebSocket connections and centralized pressure required careful concurrency handling. Key code snippets include:
go func() {
for {
select {
case data := <-r.stats.messageToRunnerChan:
data["user_count"] = r.numClients
r.outputOnEevent(data)
case <-r.closeChan:
Events.Publish("boomer:quit")
r.stop()
wg.Done()
return
}
}
}()
// Centralized pressure control
curTime := myStatus.Ct
statusTime := myStatus.St
c := time.After(time.Duration(statusTime-curTime) * time.Second)
<-c
miaosha(uidToken, &myStatus, myLog)
// Long‑lived WebSocket worker
func wsWorker() {
ws, err := websocket.Dial(wsUrl, "", origin)
if err != nil {
log.Println(err)
return
}
defer func() {
if p := recover(); p != nil {
log.Println(p)
}
if erc := ws.Close(); erc != nil {
log.Println(erc)
}
}()
go func() {
ws.Write([]byte("0"))
ticker := time.Tick(time.Second * 30)
for range ticker {
if ws == nil {
continue
}
ws.Write([]byte("0"))
fmt.Println("send 0 to websocket ok!")
}
}()
for {
select {
case <-stopChannel:
return
default:
msg := make([]byte, 512)
start := time.Now()
n, err := ws.Read(msg)
log.Println(string(msg[:n]))
if myDebug {
log.Println(string(msg))
}
if err != nil {
log.Printf("Error: %s", err.Error())
}
}
}
}3. Real‑World Deployment (818 Event) During a large‑scale live event, the system simulated up to 1 million concurrent TCP connections and 100 k QPS, dynamically adjusting load as user activity surged. Screenshots show real‑time monitoring of request counts, latency, CPU usage, and successful data reconciliation via Kafka.
4. Summary The simulation platform provides a highly extensible, stable, and scalable solution for full‑link performance testing, supporting multiple protocols and direct pressure on databases and message queues, and has been repeatedly used for company‑wide large‑scale activities.
HomeTech
HomeTech tech sharing
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.