You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对Go Web服务器做负载基准测试及解读结果?对比两种请求处理方案

Go两种请求处理方案的基准测试与结果解读

我需要对比两种Go请求处理方案的效率,核心衡量指标为:

  • 更低的最大内存占用
  • 更低的CPU使用率

这些指标用于判断哪种方案更适配资源受限的高请求量服务器——该服务器的核心需求是请求处理速度快于到达速度,此前曾因队列满、连接过多触发"too many open files"错误。

两种方案的设计思路一致:先快速响应客户端请求,再将实际业务逻辑(生产环境为HTTP请求,测试阶段用随机时长sleep模拟)放入异步队列处理。

方案A:启动固定数量协程,通过带缓冲长通道传递任务

// approach A: spin up a few goroutines at the start 
// and send messages into a long buffered channel

package main

import (
    "fmt"
    "log"
    "math/rand"
    "net/http"
    _ "net/http/pprof"
    "time"
)

const (
    minResponseTimeSec = 0.5
    maxResponeTimeSec  = 2.5
)

var messageChan = make(chan int, 1024)

func randResponseTime() float64 {
    return minResponseTimeSec + rand.Float64()*(maxResponeTimeSec-minResponseTimeSec)
}

func main() {
    rand.Seed(time.Now().UnixNano())

    for i := 1; i <= 8; i++ {
        go worker()
    }

    http.HandleFunc("/message", handler)
    log.Fatal(http.ListenAndServe(":1234", nil))
}

func handler(writer http.ResponseWriter, request *http.Request) {
    messageChan <- 3 // would normally send POST body
    fmt.Fprint(writer, "ok\n")
}

func worker() {
    for range messageChan {
        time.Sleep(time.Second * time.Duration(randResponseTime()))
    }
}

方案B:通过信号量控制最大并发协程数,按需创建协程

// approach B: set a maximum number of concurrent
// goroutines and spin them up as needed

package main

import (
    "fmt"
    "log"
    "math/rand"
    "net/http"
    _ "net/http/pprof"
    "time"
)

const (
    minResponseTimeSec = 0.5
    maxResponeTimeSec  = 2.5
)

var (
    semaphoreChan chan struct{}
)

func randResponseTime() float64 {
    return minResponseTimeSec + rand.Float64()*(maxResponeTimeSec-minResponseTimeSec)
}

func main() {
    rand.Seed(time.Now().UnixNano())

    semaphoreChan = make(chan struct{}, 1024)

    http.HandleFunc("/message", handler)
    log.Fatal(http.ListenAndServe(":1234", nil))
}

func handler(writer http.ResponseWriter, request *http.Request) {
    semaphoreChan <- struct{}{}
    go fanout() // would normally send POST body

    fmt.Fprint(writer, "ok\n")
}

func fanout() {
    defer func() { <-semaphoreChan }()
    time.Sleep(time.Second * time.Duration(randResponseTime()))
}

测试遇到的问题

我已用ab工具对两个程序进行负载测试,但无法正确解读pprof的 profiling 数据。我关注了/debug/pprof/heap?debug=1底部的TotalAlloc和HeapAlloc指标,但发现这些数值持续增长,不符合测试前后应趋于平稳的预期,怀疑选错了观测指标。

请问:如何针对这两种方案进行正确的基准测试,以及如何解读对应的测试结果?


内容的提问来源于stack exchange,提问作者xavdid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:15:46