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,只有16,383个端口。由于每个ab请求都是http/1.0(在第一个示例中没有keepalive),所以每个新请求都占用另一个端口。
ab
http/1.0
使用每个端口时,它将放入队列中,等待tcp“ Maximum Segment Lifetime”(在osx上配置为15秒)。因此,如果您在15秒钟内使用了16,383个以上的端口,则您的操作系统实际上将受到进一步连接的限制。根据哪个进程首先用尽端口,您将从服务器获得连接错误,或者从挂起ab。
您可以使用http/1.1功能强大的负载生成器(例如wrk)或对的keepalive(-k)选项来减轻这种情况ab,以便根据工具的并发设置重用连接。
http/1.1
wrk
-k
现在,您要进行基准测试的服务器代码执行得很少,以至于负载生成器的负担与服务器本身一样多,本地操作系统和网络堆栈可能会起到很大的作用。如果要对http服务器进行基准测试,最好从不在同一台计算机上运行的多个客户端进行一些有意义的工作。