http - 为什么我的 Hello World go 服务器被 ApacheBench 压垮了?

标签 http go osx-yosemite

package main

import (
    "io"
    "net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "Hello world!\n")
}

func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8000", nil)
}

我有几个非常基本的 HTTP 服务器,它们都存在这个问题。

$ ab -c 1000 -n 10000 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
apr_socket_recv: Connection refused (61)
Total of 5112 requests completed

使用较小的并发值,事情仍然会失败。对我来说,这个问题似乎通常出现在 5k-6k 左右:

$ ab -c 10 -n 10000 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
apr_socket_recv: Operation timed out (60)
Total of 6277 requests completed

事实上,您可以完全放弃并发,但问题仍然(有时)会发生:

$ ab -c 1 -n 10000 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
apr_socket_recv: Operation timed out (60)
Total of 6278 requests completed

我不禁想知道我是否在某个地方遇到了某种操作系统限制?我该怎么说?我将如何缓解?

最佳答案

简而言之,你的端口用完了。

osx 上默认的临时端口范围是 49152-65535,也就是只有 16383 个端口。由于每个 ab 请求都是 http/1.0 (在您的第一个示例中没有 keepalive),因此每个新请求都需要另一个端口。

当每个端口被使用时,它会被放入一个队列中,等待 tcp "Maximum Segment Lifetime",在 osx 上配置为 15 秒。因此,如果您在 15 秒内使用超过 16,383 个端口,您将在进一步连接时受到操作系统的限制。根据哪个进程首先耗尽端口,您将从服务器收到连接错误,或者从 ab 挂起。

您可以通过使用支持 http/1.1 的负载生成器(如 wrk)或使用 keepalive (-k) 选项来缓解这种情况ab,以便根据工具的并发设置重用连接。

现在,您进行基准测试的服务器代码做的很少,负载生成器的负担与服务器本身一样多,而本地操作系统和网络堆栈可能会做出很好的贡献。如果您想对 http 服务器进行基准测试,最好从不在同一台机器上运行的多个客户端做一些有意义的工作。

关于http - 为什么我的 Hello World go 服务器被 ApacheBench 压垮了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30352725/

相关文章:

go - Windows 和 Linux 下 Go 的不同执行

go - 无法将 StripPrefix 包装在另一个函数中(缺少 ServeHTTP 方法)

go - "Bounded"在编程中的含义

javascript - JXA 和 OmniGraffle

macos - Windows 网络上的 Yosemite 不断导致应用程序崩溃

javascript - Angularjs - 使用从远程服务器获取的 $http 显示数据

javascript - NodeJS HTTP请求未按顺序执行

java - 无法在 Mac OS X Yosemite (10.10) 上运行 java 桌面应用程序

rest - 在一个 http rest 请求中发送两个二进制消息

接受 GET/POST 请求的 HTTP 测试服务器