Skip to main content
  1. Tutorial/

简单实现QPS计算

280 words·2 mins
Golang
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)
}

Related

数据结构&控制结构实现原理
564 words·3 mins
Golang
Map 扩容条件与操作原理 # 负载因子 > 6.
Download and install - The Go Programming Language
317 words·2 mins
Kiga-Hub
Casual Essay
Golang
Download and install # Download and install Go quickly with the steps described here.
Finite State Transducer
365 words·2 mins
Note
FST # FST是一种有限状态自动机,可以用来存储和快速查找字符串集合。
Rust Book Datastructure - Arc
1242 words·6 mins
Rust
Rc 和 Arc 源码对比 # // Rc源码片段 impl<T: ?
Rust Book Datastructure - Rc
1236 words·6 mins
Rust
RC # use std::rc::Rc; use std::sync::Arc; use std::thread; fn main() { let a = Rc::new(String::from("test ref counting")); println!