如何利用所有CPU并为每个CPU生成http进程?
获取数量的CPU
numCPU := runtime.NumCPU()
启动http
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
答案 0 :(得分:5)
如果你的目标只是让你的请求处理代码在所有CPU内核上运行,那么net/http
已经启动了goroutine(一个类似线程的模糊事物特定于Go的实现)每个连接,并且Go安排NumCPU
OS线程默认运行,以便goroutine可以分布在所有可用的CPU核心上。
Accept
循环在单个goroutine中运行,但解析请求和生成响应的实际工作在每个连接中运行一次。
答案 1 :(得分:1)
你不能天真地,你必须编写自己的包装器:
// copied from http://golang.org/src/pkg/net/http/server.go#L1942
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}
func ListenAndServe(addr string, num int) error {
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
var wg sync.WaitGroup
for i := 0; i < num; i++ {
wg.Add(1)
go func(i int) {
log.Println("listener number", i)
log.Println(http.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}, nil))
wg.Done()
}(i)
}
wg.Wait()
return nil
}
func main() {
num := runtime.NumCPU()
runtime.GOMAXPROCS(num) //so the goroutine listeners would try to run on multiple threads
log.Println(ListenAndServe(":9020", num))
}
或者,如果您使用最新的Linux内核,则可以使用http://comments.gmane.org/gmane.comp.lang.go.general/121122中的补丁并实际生成多个进程。