英文:
Google Go: Why does the http server package not serve more than 5 simultaneous requests?
问题
我正在尝试使用Google的Go语言编写一个小型的HTTP服务器,以便以后进行扩展。我正在使用Windows上的Go(MinGw编译版本)。
在这种语言中,这是相当容易的,因为它已经有了必要的包:
package main
import (
"http"
"io"
"os"
"fmt"
"strconv"
)
func FileTest(w http.ResponseWriter, req *http.Request) {
w.Header().Add("Content-Type", "image/jpeg")
w.Header().Add("Content-Disposition", "inline; filename=image.jpg")
inName := "d:\\googlego\\somepic.jpg"
inFile, inErr := os.OpenFile(inName, os.O_RDONLY, 0666)
if inErr == nil {
inBufLen := 16
inBuf := make([]byte, inBufLen)
_, inErr := inFile.Read(inBuf)
for inErr == nil {
w.Write(inBuf)
_, inErr = inFile.Read(inBuf)
}
}
inErr = inFile.Close()
}
func MainPage(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hi, download here: <a href=\"/FileTest\">HERE</a>")
}
func main() {
fmt.Print("Port: ")
var hi int
fmt.Scanf("%d", &hi)
http.HandleFunc("/FileTest", FileTest)
http.HandleFunc("/", MainPage)
err := http.ListenAndServe("0.0.0.0:" + strconv.Itoa(hi), nil)
if err != nil {
fmt.Print(err)
fmt.Print((hi))
}
}
这将启动一个服务器,提供一个主页和一个从图像下载。两者都工作得非常好,我从ab(Apache基准测试工具)中得到了非常好的结果,最多可以同时处理6个线程:
> ab -n 10000 -c 6 http://localhost:8080/
Concurrency Level: 6
Time taken for tests: 1.678096 seconds
Complete requests: 10000
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 1
80% 1
90% 2
95% 2
98% 2
99% 2
100% 3 (longest request)
当并发级别设置得更高时,情况如下:
> ab -n 1000 -c 7 http://localhost:8080/
Concurrency Level: 7
Time taken for tests: 10.239586 seconds
Complete requests: 1000
Percentage of the requests served within a certain time (ms)
50% 1
66% 2
75% 2
80% 3
90% 499
95% 505
98% 507
99% 507
100% 510 (longest request)
请注意,这次我只进行了1,000个请求,但时间几乎增加了6倍。
这两个基准测试甚至还没有请求文件。
我对Go还不是很了解,但似乎Go运行时没有创建足够的操作系统线程来放置goroutine,或者类似的情况?
编辑:我下载了2011年10月7日的新版本r60.2。
现在情况变得更糟了:
> ab -c 7 -n 1000 http://localhost:8080/
Concurrency Level: 7
Time taken for tests: 12.622722 seconds
Complete requests: 1000
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 2
80% 2
90% 496
95% 503
98% 506
99% 506
100% 507 (longest request)
英文:
I'm trying to code a small http server for later extension in Google's Go language. I am using Go on Windows (MinGw compiled version).
This is quite easy in this language since it already has the necessary package:
package main
import (
"http"
"io"
"os"
"fmt"
"strconv"
)
func FileTest(w http.ResponseWriter, req *http.Request) {
w.Header().Add("Content-Type", "image/jpeg")
w.Header().Add("Content-Disposition", "inline; filename=image.jpg")
inName := "d:\\googlego\\somepic.jpg";
inFile, inErr := os.OpenFile(inName, os.O_RDONLY, 0666);
if inErr == nil {
inBufLen := 16;
inBuf := make([]byte, inBufLen);
_, inErr := inFile.Read(inBuf);
for inErr == nil {
w.Write(inBuf)
_, inErr = inFile.Read(inBuf);
}
}
inErr = inFile.Close();
}
func MainPage(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hi, download here: <a href=\"/FileTest\">HERE</a>")
}
func main() {
fmt.Print("Port: ")
var hi int
fmt.Scanf("%d", &hi)
http.HandleFunc("/FileTest", FileTest)
http.HandleFunc("/", MainPage)
err := http.ListenAndServe("0.0.0.0:" + strconv.Itoa(hi), nil)
if err != nil {
fmt.Print(err)
fmt.Print((hi))
}
}
This starts a server that serves a main page and a download from an image. Both work very well and I get very good results from ab (Apache benchmark) up to 6 concurrent threads:
> ab -n 10000 -c 6 http://localhost:8080/
Concurrency Level: 6
Time taken for tests: 1.678096 seconds
Complete requests: 10000
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 1
80% 1
90% 2
95% 2
98% 2
99% 2
100% 3 (longest request)
When the concurrency level is set higher, this happens:
>ab -n 1000 -c 7 http://localhost:8080/
Concurrency Level: 7
Time taken for tests: 10.239586 seconds
Complete requests: 1000
Percentage of the requests served within a certain time (ms)
50% 1
66% 2
75% 2
80% 3
90% 499
95% 505
98% 507
99% 507
100% 510 (longest request)
Note that I only made 1'000 requests this time and it still took almost 6 times as much time.
Both benchmarks don't even request the file yet.
I don't know a lot about Go yet, but it seems that the Go runtime doesn't create enough OS threads to put the goroutines on, or something like that?
EDIT: I downloaded the new r60.2 from 07.10.2011.
Now it went even worse:
>ab -c 7 -n 1000 http://localhost:8080/
Concurrency Level: 7
Time taken for tests: 12.622722 seconds
Complete requests: 1000
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 2
80% 2
90% 496
95% 503
98% 506
99% 506
100% 507 (longest request)
答案1
得分: 4
截至今天(2011年9月),Go语言在Windows平台上的移植仍在进行中。它在一些重要的方面,包括稳定性和性能(尽管每天都在改进),落后于其他支持的平台(如Linux等)。我建议您在64位Linux平台上进行测试,看看它与Windows平台有何不同,然后也许您可以开始分析在Windows下出了什么问题。
英文:
As of today (Sep 2011) the Windows port of Go is a work-in-progress. It lags behind the other supported platforms (Linux, etc.) in some important measures including stability and performance (though it is improving every day). I would suggest that you try your test on a 64-bit Linux platform, and see how it differs, then maybe you can start deconstructing what's going wrong under Windows.
答案2
得分: 2
我刚刚在Go 64位的tip上尝试了这个基准测试,并得到了以下结果(在Core 2 Duo 2GHz,Windows 7 x64上):
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin>ab -c 7 -n 1000 http://localhost:8080/
并发级别:7
测试所用时间:0.458秒
完成请求数:1000
在特定时间内完成请求的百分比(毫秒)
50% 3
66% 3
75% 3
80% 3
90% 4
95% 5
98% 7
99% 8
100% 9(最长的请求)
英文:
I just tried this benchmark with Go 64-bit at tip, and got the following results (on a Core 2 Duo 2GHz, Windows 7 x64):
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin>ab -c 7 -n 1000 http://localhost:8080/
Concurrency Level: 7
Time taken for tests: 0.458 seconds
Complete requests: 1000
Percentage of the requests served within a certain time (ms)
50% 3
66% 3
75% 3
80% 3
90% 4
95% 5
98% 7
99% 8
100% 9 (longest request)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论