Golang http服务器在启动无限循环的goroutine时阻塞
正如我从golang docs中学到的,如果我将runtime.GOMAXPROCS(8)设置为8核cpu(intel i7),然后启动一个无限循环的goroutine,其他gorutine就不应该被阻塞,因为有engough线程和goprocs。但当使用net/http包时,情况并非如此,一个无限循环goroutine将在几次调用后阻塞http服务器。 有人能解释一下原因吗Golang http服务器在启动无限循环的goroutine时阻塞,http,go,block,goroutine,Http,Go,Block,Goroutine,正如我从golang docs中学到的,如果我将runtime.GOMAXPROCS(8)设置为8核cpu(intel i7),然后启动一个无限循环的goroutine,其他gorutine就不应该被阻塞,因为有engough线程和goprocs。但当使用net/http包时,情况并非如此,一个无限循环goroutine将在几次调用后阻塞http服务器。 有人能解释一下原因吗 如果我注释“go infinite loop”一行,在服务器之后启动客户端,客户端将输出1000个星号;但如果我启用go
如前所述,空循环应在独立线程中执行,其他goroutine不应受到忙循环的影响。我的理解有什么问题?调度程序可能无法抢占这样一个空的“无限”循环。调度器在上一个版本中变得越来越好,也许他应该足够好,可以编写这样的代码;他绝对是足够好的真正的代码。别胡闹了 Go运行时的调度程序。Go 1.2改进了问题,但是您的示例中的无限循环没有函数调用,因此这没有帮助
使用无限循环处理程序的实际主体,您可能会看到更好的行为。或者,在这种情况下,手动调用可能会有所帮助。一个“无限”循环不是问题。这是一个繁忙的循环,只会烧坏CPU,这是个问题。@GrzegorzŻur您确定客户端可以打印所有1000个星号吗?我交叉编译了源文件,并在linux/amd64平台上运行它们。客户之前打印了大约150个星号halted@user922965我的错误,我运行它的临界线注释掉了。我重做了测试,它被阻塞了。我得到了同样的暂停,这是意外的,一定是调度程序的一个限制?可能会提交错误报告:)我使用go1.4beta1 linux/amd64版本运行代码,但它没有打印一个字符:-(我认为这是一个很好的问题。我又增加了一个关于LockOfThread的问题,你能给出更多的建议吗?也许这有助于准确描述你正在尝试做的事情。当然你在真实的程序中没有使用空无限循环,那么你到底想知道什么呢?我试图比较golang和java nio之间的http性能,不是吗这是一个边缘案例,一些核心被其他应用程序耗尽,无法被http服务器使用。您的链接解决了我的问题。实际上,我只是想知道为什么“LockOSThread”不起作用,请尝试了解golang scheduler的更多信息。我不确定
LockOSThread
是否实际分配了另一个线程来运行Go code。如果没有,那么在这里就没有任何帮助。如果你想尝试减少应用程序运行的内核数量以进行测试,也许可以看看你的操作系统的CPU亲和性在Linux上,taskset
实用程序可能会起到作用。
package main
import (
"fmt"
"log"
"net/http"
"runtime"
)
func myHandler(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("hello"))
}
func infiniteloop() {
for {
}
}
func main() {
// set max procs for multi-thread executing
runtime.GOMAXPROCS(runtime.NumCPU())
// print GOMAXPROCS=8 on my computer
fmt.Println("GOMAXPROCS=", runtime.GOMAXPROCS(-1))
http.Handle("/", http.HandlerFunc(myHandler))
// uncomment below line cause server block after some requests
// go infiniteloop()
if err := http.ListenAndServe(":8280", nil); err != nil {
log.Fatal(err)
}
}
package main
import (
"fmt"
"net/http"
)
func getOnce() {
if resp, err := http.Get("http://localhost:8280"); err != nil {
fmt.Println(err)
return
} else {
defer func() {
if err := resp.Body.Close(); err != nil {
fmt.Println(err)
}
}()
if resp.StatusCode != 200 {
fmt.Println("error codde:", resp.StatusCode)
return
} else {
fmt.Print("*")
}
}
}
func main() {
for i := 1; i < 1000; i++ {
getOnce()
if i%50 == 0 {
fmt.Println()
}
}
}