为什么这个 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/test1
、http://localhost:8080/test2
等打开多个选项卡,您将获得预期的结果。这表明 Chrome 中确实存在一些用于匹配 URL 的排队机制。
以前的标题:如何为每个 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/test1
、http://localhost:8080/test2
等打开多个选项卡,您将获得预期的结果。这表明 Chrome 中确实存在一些用于匹配 URL 的排队机制。