使用ListenAndServe的Goroutines可以提高性能吗?

时间:2015-05-27 16:05:21

标签: concurrency go

我对Go的例程并不是很熟悉,但是因为我正在使用net/http的路由器,所以我看到ListenAndServe()被一个例行程序包裹了几次。

服务器需要能够同时处理多个请求以提高效率。那么为什么要使用例程作为“轻量级线程”呢? 并发性是否具有任何优势?

以下是OpenShift的示例

package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello OpenShift!")
}

func main() {
    http.HandleFunc("/", helloHandler)

    go func() {
        fmt.Println("serving on 8080")
        err := http.ListenAndServe(":8080", nil)
        if err != nil {
            panic("ListenAndServe: " + err.Error())
        }
    }()

    go func() {
        fmt.Println("serving on 8888")
        err := http.ListenAndServe(":8888", nil)
        if err != nil {
            panic("ListenAndServe: " + err.Error())
        }
    }()
    select {}
}

3 个答案:

答案 0 :(得分:11)

http.ListenAndServe是一个阻止通话。如果你想做一个更多的工作(比如进行第二次http.ListenAndServe调用),你需要把它移到一个单独的goroutine上。这就是他们在这里所做的一切。

他们最后使用select{}来阻止主goroutine,因为他们对http.ListenAndServe的所有调用都在其他goroutine上。如果他们没有调用select{},程序将会终止,因为main()会返回。

他们可以通过删除select{}并删除最后一个代码块周围的go func()包装器来实现相同的功能。但我怀疑他们是这样做的,所以所有代码都是一致的。

但这与表现无关。

在评论中,您提供了一些类似的其他示例。在first example

func main() {
    http.HandleFunc("/", responsehandler.Handler)
    go func() {
      http.ListenAndServe(":8888", nil)
    }()
    fileservice.NewWatcher()
}

这会调用http.ListenAndServe,然后调用fileservice.NewWatcher()(阻止)。如果他们没有将调用包裹在goroutine中,则fileservice.NewWatcher()永远不会被调用。

另一个two examples是一个常见的样板:

func init() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()
}

这将打开调试分析器Web服务器。同样,它是一个goroutine,因此调用init会立即返回而不是阻塞。这种特殊情况允许呼叫者只是import _ "profiling"和"神奇地"获取调试分析器Web服务器。

答案 1 :(得分:1)

除了“在后台运行”之外,它没有任何特殊的好处。

答案 2 :(得分:0)

我认为你不需要一个go例程来启动ListenAndServe。根据Go Documentations。

“ListenAndServe调用Serve”。服务是常规。

ListenAndServe侦听TCP网络地址addr,然后使用处理程序调用Serve来处理传入连接上的请求。接受的连接配置为启用TCP保持活动。处理程序通常为零,在这种情况下使用DefaultServeMux。 https://golang.org/pkg/net/http/#ListenAndServe

func Serve(l net.Listener,handler Handler)错误 Serve接受侦听器l上的传入HTTP连接,为每个连接创建一个新的服务goroutine。服务goroutines读取请求,然后调用处理程序来回复它们。处理程序通常为零,在这种情况下使用DefaultServeMux。 https://golang.org/pkg/net/http/#Serve