【问题标题】:Can't overcome 4000 RPS treshold on localhost HTTP Golang server无法克服 localhost HTTP Golang 服务器上的 4000 RS 阈值
【发布时间】:2020-09-27 21:39:33
【问题描述】:

我尝试在本地机器上测量 Go 默认 HTTP 服务器实现的带宽。服务器只是接受任何 HTTP 请求,使用 sync.atomic 递增计数器并发送 200 OK 响应。此外,服务器每秒收集请求数量,将其打印出来并将计数器重置为零:

type hand struct {
    cnt int32
}

func (h *hand) ServeHTTP(rsp http.ResponseWriter, req *http.Request) {
    atomic.AddInt32(&h.cnt, 1)
    rsp.WriteHeader(200)
    if req.Body != nil {
        req.Body.Close()
    }
}

func main() {
    h := new(hand)
    s := &http.Server{
        Addr:    ":8080",
        Handler: h,
    }
    ticker := time.NewTicker(1 * time.Second)
    go func() {
        for tick := range ticker.C {
            val := atomic.SwapInt32(&h.cnt, 0)
            fmt.Printf("(%v) %d RPS\n", tick, val)
        }
    }()
    log.Fatal(s.ListenAndServe())
}

目标客户端正在尝试同时发送 100000 个GET 请求:

const total = 100000

func main() {
    var r int32
    var rsp int32
    r = total
    rsp = r
    for r > 0 {
        go func() {
            p, err := http.Get("http://localhost:8080")
            atomic.AddInt32(&rsp, -1)
            if err != nil {
                fmt.Printf("error: %s\n", err)
                return
            }
            if p.StatusCode != 200 {
                fmt.Printf("status %d\n", p.StatusCode)
            }
        }()
        r--

    }
    for {
        x := atomic.LoadInt32(&rsp)
        fmt.Printf("sent : %d\n", total-x)
        if x == 0 {
            return
        }
        time.Sleep(1 * time.Second)
    }
}

我正在使用带有5.3.2-gentoo 内核的Linux 机器。我将nofileulimitssofthard)更改为100000。当我运行这个测试时,所有其他用户应用程序都停止了。

我不希望得到准确的结果,但只需要知道这个阈值的水平,例如X000X0000X00000

但是服务器每秒处理的请求数不能超过4000,看起来太低了:

# removed timestamps
0 RPS
0 RPS
0 RPS
3953 RPS
3302 RPS
387 RPS
37 RPS
1712 RPS

如何提高 HTTP 服务器的带宽?还是我的测试方法或本地配置有问题?

【问题讨论】:

  • 计算带宽的方式不是最优的。自动收报机不是时间的可靠度量。您应该让计数器值递增并将其值除以经过的时间,以获得每秒的平均滴答数。另一个问题是您的客户端中缺少p.Body.Close()。不确定它是否会影响性能,但肯定会影响内存管理。
  • 开始 10000 个 goroutine 不好。主意。你的电脑有10000核吗?它们将按顺序执行并减慢执行速度。您应该开始少量 goroutine 并增加数量,直到您看不到性能变化为止。
  • 尝试使用现有的基准测试工具,例如wrk,这样您只需要担心改进服务器。
  • 看在上帝的份上,请使用正确的设置。在服务器和客户端都在开发机器上运行的情况下“测量”服务器实现的性能(它并行执行各种事情,并且很可能会遇到打开文件数量等限制)就像测量你的身体将您的自己的手放在额头上来测量温度。将服务器放到目标平台上,测量它可以可靠地满足您的用例的请求数量。这个数字减去一点是水平缩放的缩放阈值。问题解决了。
  • 以上所有和fmt.Println 可能不会在收到报价后立即发生。

标签: performance http go


【解决方案1】:

问题出在测试方法上:

  1. 在同一台机器上运行客户端和服务器是不正确的,目标服务器应该位于专用主机上,目标和客户端之间的网络应该足够快
  2. 不能选择用于网络测试的自定义脚本:对于简单的情况可以使用wrk,对于更复杂的情况Jmetr 或其他框架可以使用

当我使用wrk 在专用主机上测试此服务器时,它显示285900.73 RPS。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 2015-04-20
    • 2013-07-15
    • 2020-08-26
    • 1970-01-01
    • 2018-10-14
    • 2017-11-13
    相关资源
    最近更新 更多