duancai1904
2015-05-27 16:05
浏览 153
已采纳

带ListenAndServe的Goroutine可以提高性能吗?

I'm not very familiar with Go's routines but since I'm working with the router of net/http I saw a few times thatListenAndServe() is wrapped by a go routine.

A server needs to be able to handle multiple requests simultaneously out of the box to be efficient. So why are go routines as 'lightweight threads' used? Does the concurrency provide any advantages?

Here's an example by 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 {}
}

图片转代码服务由CSDN问答提供 功能建议

我对Go的例程不是很熟悉,但是由于我正在使用 net /的路由器 http 我几次看到 ListenAndServe()被go例程包装了。

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

这里是 OpenShift

 包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(“服务于8080”)
 err:= http.ListenAndServe(  “:8080”,nil)
如果错误!= nil {
 panic(“ ListenAndServe:” + err.Error())
} 
}()
 
 go func(){
 fmt  .Println(“ serving on 8888”)
 err:= http.ListenAndServe(“:8888”,nil)
 if err!= nil {
 panic(“ ListenAndServe:” + err.Error())
  } 
}()
选择{} 
} 
   
 
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dongpi2503 2015-05-27 16:31
    已采纳

    http.ListenAndServe is a blocking call. If you want to go one doing more work (like making a second http.ListenAndServe call), you need to move it over to a separate goroutine. That's all they're doing here.

    They're using select{} at the end to block the main goroutine, since all their calls to http.ListenAndServe are on other goroutines. If they didn't call select{}, the program would terminate because main() would return.

    They could have achieved the same thing by dropping select{}, and removing the go func() wrapper around the last block of code. But I suspect they did it this way so that all the code is consistent.

    But this has nothing to do with performance.

    In the comments you provided some other examples that are similar. In the first example:

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

    This calls http.ListenAndServe and then calls fileservice.NewWatcher() (which blocks). If they hadn't wrapped the call in a goroutine, fileservice.NewWatcher() would never have been called.

    The other two examples are a common piece of boilerplate:

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

    This turns on the debug profiler web server. Again, it's a goroutine so that calling init returns immediately rather than blocking. This particular case allows the caller to just import _ "profiling" and "magically" get the debug profiler web server.

    打赏 评论
  • dousi4950 2015-05-27 16:25

    No it does not have any special benefits beside being "run in the background".

    打赏 评论
  • duanbo1659 2018-05-05 14:13

    I don't think you need a go routine to start ListenAndServe. According to the Go Documentations.

    "ListenAndServe calls Serve". Serve is go routine.

    ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections. Accepted connections are configured to enable TCP keep-alives. Handler is typically nil, in which case the DefaultServeMux is used. https://golang.org/pkg/net/http/#ListenAndServe

    func Serve(l net.Listener, handler Handler) error Serve accepts incoming HTTP connections on the listener l, creating a new service goroutine for each. The service goroutines read requests and then call handler to reply to them. Handler is typically nil, in which case the DefaultServeMux is used. https://golang.org/pkg/net/http/#Serve

    打赏 评论

相关推荐 更多相似问题