Simple QPS #
实现一个简单的QPS(每秒查询率)测试。
创建一个指定数量的HTTP请求,并使用多个Go协程并发地发送这些请求。然后,计算发送所有请求所需的时间,并使用这个时间来计算QPS。
-
定义测试参数:定义要发送的请求数量(
numRequests
),要使用的Go协程数量(numThreads
),以及要请求的URL。 -
创建HTTP请求:创建一个新的HTTP GET请求。
-
并发发送HTTP请求:创建
numThreads
个Go协程,每个协程都会发送numRequests/numThreads
个请求。使用一个sync.WaitGroup
来等待所有的请求都被发送。 -
计算并输出QPS:计算发送所有请求所需的时间(
elapsed
),然后使用这个时间和请求数量来计算QPS。
package main
import (
"fmt"
"net/http"
"sync"
"time"
)
func main() {
// 定义测试参数
numRequests := 10000
numThreads := 10
url := "http://192.168.8.244:31002/api/mgmt/v1/health"
// 创建HTTP请求
request, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("Failed to create request:", err)
return
}
// 并发-发送HTTP请求
var wg sync.WaitGroup
wg.Add(numRequests)
start := time.Now()
for i := 0; i < numThreads; i++ {
go func() {
client := http.DefaultClient
for j := 0; j < numRequests/numThreads; j++ {
_, err := client.Do(request)
if err != nil {
fmt.Println("Failed to send request:", err)
}
wg.Done()
}
}()
}
wg.Wait()
elapsed := time.Since(start)
// 输出测试结果
qps := float64(numRequests) / elapsed.Seconds()
fmt.Printf("QPS: %.2f\n", qps)
}
错误处理、超时、重试 #
创建一个带缓冲的通道concurrency来限制并发数,以及一个错误通道errChan来收集错误。
设置HTTP客户端的超时,并在请求失败时进行重试。最后计算QPS时只考虑成功的请求。
package main
import (
"fmt"
"net/http"
"sync"
"time"
)
const (
numRequests = 10000
numThreads = 10
maxRetries = 3
timeout = 2 * time.Second
)
var (
url = "http://192.168.8.244:31002/api/mgmt/v1/health"
client = &http.Client{Timeout: timeout}
concurrency = make(chan struct{}, numThreads)
errChan = make(chan error, numRequests)
wg sync.WaitGroup
)
func sendRequest(request *http.Request) {
defer wg.Done()
for i := 0; i < maxRetries; i++ {
concurrency <- struct{}{}
_, err := client.Do(request)
<-concurrency
if err != nil {
errChan <- err
time.Sleep(timeout)
continue
}
errChan <- nil
return
}
}
func main() {
request, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("Failed to create request:", err)
return
}
wg.Add(numRequests)
start := time.Now()
for i := 0; i < numRequests; i++ {
go sendRequest(request)
}
wg.Wait()
close(errChan)
var successCount int
for err := range errChan {
if err == nil {
successCount++
}
}
elapsed := time.Since(start)
qps := float64(successCount) / elapsed.Seconds()
fmt.Printf("QPS: %.2f\n", qps)
}