为什么这个 go HTTP 服务器不在 Chrome 47 中为每个请求生成一个 goroutine?

Why isn't this go HTTP server spawning a goroutine per request in Chrome 47?

以前的标题:如何为每个 HTTP 请求生成 goroutine?

下面的代码是一个简单的 HTTP 服务器,它将路径回显给请求者。我用它来测试 net/http 包的 ListenAndServe 方法是否默认触发一个 goroutine 来处理每个请求;我发现它没有。如果我同时发出三个请求,第一个 return 需要 10 秒,第二个 20(第一个 returns 后 10 秒),第三个 30 秒。

package main

import (
  "fmt"
  "net/http"
  "time"
)

func handler(w http.ResponseWriter, r *http.Request) {
  time.Sleep(10000 * time.Millisecond)
  fmt.Fprint(w, r.URL.Path)
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":8080", nil)
}

基本上我想要的是主 goroutine 来侦听 HTTP 连接,然后将请求的读取和响应传递给另一个 goroutine 中生成的处理程序。

有人可以指出我完成此任务的正确方向吗?最好在 go.

中使用 net/http

更新 12/21/15 08:46 上午 MST

我使用我的网络浏览器 (chrome 47) 进行了完全相同的测试,在 localhost:8080 的根目录下进行了五个请求,结果大致为:

1st: 10 seconds
2nd: 20 seconds
3rd: 30 seconds
4th: 36 seconds     
5th: 38 seconds

所以,希望那些 down-vote 我的问题的人能够理解我的困惑以及我为什么做出我所做的假设。我不知道为什么我在第 4 次和第 5 次请求时得到了结果。

我 运行 使用 curl 进行了相同的测试,结果与 @tomasz 相同。

我正在使用 go1.2.1

更新 12/21/15 02:08 下午 MST

根据下面@tomasz 的建议,我将这个问题的标题从 "How to spawn goroutine per HTTP request" 改为 "Why isn't this go HTTP server spawning a goroutine per request in Chrome 47?"

一切都很好,您的处理程序 运行 在每个请求的单独例程中。看看 http.Server.Serve 方法的源代码。接受循环的最后一行说:

go c.serve()

问题可能出在您的测试上。如果您通过浏览器中的多个选项卡检查行为,匹配 URL 的请求可能会排队,而不是同时 运行ning 它们(即您的客户端没有使用 "routines",而不是服务器)。

尝试两种不同的浏览器,或者只使用命令行,比如 curl 来并行测试请求。例如(在 bash 的帮助下):

$ for i in {1..5}; do time curl localhost:8080 &; done
# after ignoring some mess...
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.013 total
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.014 total
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.012 total
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.019 total

你的服务器工作得很好。

更新

我可以在 Chrome 47 上确认此行为,但也注意到您可以使用 http://localhost:8080/test1http://localhost:8080/test2 等打开多个选项卡,您将获得预期的结果。这表明 Chrome 中确实存在一些用于匹配 URL 的排队机制。