package main import ( "encoding/json" "fmt" "io" "net/http" "sync" "sync/atomic" "time" ) // 压测配置 type BenchConfig struct { URL string // 测试URL Concurrency int // 并发数 Duration time.Duration // 持续时间 Timeout time.Duration // 请求超时时间 } // 压测结果 type BenchResult struct { TotalRequests int64 // 总请求数 SuccessRequests int64 // 成功请求数 FailedRequests int64 // 失败请求数 TotalDuration time.Duration // 总耗时 MinLatency time.Duration // 最小延迟 MaxLatency time.Duration // 最大延迟 AvgLatency time.Duration // 平均延迟 QPS float64 // 每秒请求数 } func main() { fmt.Println("==========================================") fmt.Println(" HoTime 框架性能压力测试") fmt.Println("==========================================") fmt.Println() // 测试配置 configs := []BenchConfig{ { URL: "http://127.0.0.1:8081/app/test/hello", Concurrency: 10, Duration: 10 * time.Second, Timeout: 5 * time.Second, }, { URL: "http://127.0.0.1:8081/app/test/hello", Concurrency: 50, Duration: 10 * time.Second, Timeout: 5 * time.Second, }, { URL: "http://127.0.0.1:8081/app/test/hello", Concurrency: 100, Duration: 10 * time.Second, Timeout: 5 * time.Second, }, { URL: "http://127.0.0.1:8081/app/test/hello", Concurrency: 200, Duration: 10 * time.Second, Timeout: 5 * time.Second, }, } // 先检查服务是否可用 fmt.Println("正在检查服务是否可用...") if !checkService(configs[0].URL) { fmt.Println("❌ 服务不可用,请先启动示例应用:") fmt.Println(" cd example && go run main.go") return } fmt.Println("✅ 服务已就绪") fmt.Println() // 执行压测 for i, config := range configs { fmt.Printf("【测试 %d】并发数: %d, 持续时间: %v\n", i+1, config.Concurrency, config.Duration) fmt.Println("------------------------------------------") result := runBenchmark(config) printResult(result) fmt.Println() // 测试间隔,让服务恢复 if i < len(configs)-1 { fmt.Println("等待 3 秒后开始下一轮测试...") time.Sleep(3 * time.Second) fmt.Println() } } fmt.Println("==========================================") fmt.Println(" 压力测试完成") fmt.Println("==========================================") } // 检查服务是否可用 func checkService(url string) bool { client := &http.Client{Timeout: 3 * time.Second} resp, err := client.Get(url) if err != nil { return false } defer resp.Body.Close() return resp.StatusCode == 200 } // 执行压测 func runBenchmark(config BenchConfig) BenchResult { var ( totalRequests int64 successRequests int64 failedRequests int64 totalLatency int64 // 纳秒 minLatency int64 = int64(time.Hour) maxLatency int64 mu sync.Mutex ) // 创建HTTP客户端 client := &http.Client{ Timeout: config.Timeout, Transport: &http.Transport{ MaxIdleConns: config.Concurrency * 2, MaxIdleConnsPerHost: config.Concurrency * 2, IdleConnTimeout: 90 * time.Second, }, } // 控制退出 done := make(chan struct{}) var wg sync.WaitGroup startTime := time.Now() // 启动并发goroutine for i := 0; i < config.Concurrency; i++ { wg.Add(1) go func() { defer wg.Done() for { select { case <-done: return default: reqStart := time.Now() success := makeRequest(client, config.URL) latency := time.Since(reqStart).Nanoseconds() atomic.AddInt64(&totalRequests, 1) atomic.AddInt64(&totalLatency, latency) if success { atomic.AddInt64(&successRequests, 1) } else { atomic.AddInt64(&failedRequests, 1) } // 更新最小/最大延迟 mu.Lock() if latency < minLatency { minLatency = latency } if latency > maxLatency { maxLatency = latency } mu.Unlock() } } }() } // 等待指定时间 time.Sleep(config.Duration) close(done) wg.Wait() totalDuration := time.Since(startTime) // 计算结果 result := BenchResult{ TotalRequests: totalRequests, SuccessRequests: successRequests, FailedRequests: failedRequests, TotalDuration: totalDuration, MinLatency: time.Duration(minLatency), MaxLatency: time.Duration(maxLatency), } if totalRequests > 0 { result.AvgLatency = time.Duration(totalLatency / totalRequests) result.QPS = float64(totalRequests) / totalDuration.Seconds() } return result } // 发起单个请求 func makeRequest(client *http.Client, url string) bool { resp, err := client.Get(url) if err != nil { return false } defer resp.Body.Close() // 读取响应体 body, err := io.ReadAll(resp.Body) if err != nil { return false } // 验证响应 if resp.StatusCode != 200 { return false } // 验证JSON格式 var result map[string]interface{} if err := json.Unmarshal(body, &result); err != nil { return false } // 验证返回状态 if status, ok := result["status"].(float64); !ok || status != 0 { return false } return true } // 打印结果 func printResult(result BenchResult) { successRate := float64(result.SuccessRequests) / float64(result.TotalRequests) * 100 fmt.Printf("总请求数: %d\n", result.TotalRequests) fmt.Printf("成功请求: %d\n", result.SuccessRequests) fmt.Printf("失败请求: %d\n", result.FailedRequests) fmt.Printf("成功率: %.2f%%\n", successRate) fmt.Printf("总耗时: %v\n", result.TotalDuration.Round(time.Millisecond)) fmt.Printf("QPS: %.2f 请求/秒\n", result.QPS) fmt.Printf("最小延迟: %v\n", result.MinLatency.Round(time.Microsecond)) fmt.Printf("最大延迟: %v\n", result.MaxLatency.Round(time.Microsecond)) fmt.Printf("平均延迟: %v\n", result.AvgLatency.Round(time.Microsecond)) // 性能评级 fmt.Print("性能评级: ") switch { case result.QPS >= 10000: fmt.Println("🚀 优秀 (QPS >= 10000)") case result.QPS >= 5000: fmt.Println("⭐ 良好 (QPS >= 5000)") case result.QPS >= 2000: fmt.Println("👍 中等 (QPS >= 2000)") case result.QPS >= 1000: fmt.Println("📊 一般 (QPS >= 1000)") default: fmt.Println("⚠️ 需优化 (QPS < 1000)") } }