2014-09-28 35 views
1

如何利用所有的CPU并为每个CPU产生一个http进程? CPU的如何通过http使用多个进程

获取NUM

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) 
} 

回答

5

如果你的目标只是让你的请求处理代码上的所有CPU核上运行,net/http已经开始goroutine每个连接(一个模糊的线索,像围棋,具体实施的事情)。您只需在程序开始时使用runtime.GOMAXPROCS(runtime.NumCPU())以允许goroutine在多个核心上运行。

Accept循环在单个goroutine中运行,但解析请求和生成响应的实际工作在每个连接中运行一次。

此行数量将是错误的未来该怎么走的版本,但现在你可以看到实际的go声明丢给够程在http://golang.org/src/pkg/net/http/server.go#L1721

+0

在node.js的大多是多连接和其他一些实现(进程不是多线程的),接受在多个“进程”/“线程”上运行。我认为这就是他的意思,但我可以完全离开这里。 – OneOfOne 2014-09-28 18:32:24

+0

只是澄清说,只有请求处理在goroutines(当我看到您的评论时正在写入该添加!)。老实说不确定他们想要什么,所以留给他们看。 – twotwotwo 2014-09-28 18:36:29

+0

在nodejs中,你必须使用'cluster'为每个CPU产生一个新的线程。但是在Go中你只需要设置'runtime.GOMAXPROCS(runtime.NumCPU())'来实现相同的目标呢?这是否正确:) – clarkk 2014-09-28 19:19:55

1

你不能nativly,你必须写自己的包装:

// 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 Kernel,你可以使用来自http://comments.gmane.org/gmane.comp.lang.go.general/121122的补丁,并且实际上产生多个进程。