Skip to main content

简单实现QPS计算

Golang
KIGA
Author
KIGA
This is a personal blog, intended for sharing.
Table of Contents

Simple QPS
#

实现一个简单的QPS(每秒查询率)测试。

创建一个指定数量的HTTP请求,并使用多个Go协程并发地发送这些请求。然后,计算发送所有请求所需的时间,并使用这个时间来计算QPS。

  1. 定义测试参数:定义要发送的请求数量(numRequests),要使用的Go协程数量(numThreads),以及要请求的URL。

  2. 创建HTTP请求:创建一个新的HTTP GET请求。

  3. 并发发送HTTP请求:创建numThreads个Go协程,每个协程都会发送numRequests/numThreads个请求。使用一个sync.WaitGroup来等待所有的请求都被发送。

  4. 计算并输出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)
}