繁体   English   中英

Golang:去goroutine还是不去goroutine?

[英]Golang: to goroutine or not to goroutine?

在Go中开发http服务器时,很多时候我遇到了这个难题。

假设我想以http statuscode 200尽快响应客户端(然后在后面执行工作),这就是我通常这样做的原因:

我让我的主要http处理程序接收到请求,并在响应中写入http 200 ,然后通过一个channel发送一条消息(如果我有N工作人员在该channel上侦听,我正在使用Nbuffered channel ):

func myHttpHandler(rw http.ResponseWriter, req *http.Request) {
    rw.WriteHeader(200)
    log(req)
}

func log(req *http.Request) {
    msg := createLog(req)
    if msg != nil {
        channel <- msg
    }
}

我的听众(在init上解雇了)永远在该频道上听:

func init() {
    for i := 0; i < workerCount; i++ {
        go worker(i, maxEntrySize, maxBufferSize, maxBufferTime)
    }
}

func worker(workerID int, maxEntrySize int, maxBufferSize int, maxBufferTime time.Duration) {
    for {
        entry := <-channel
        ...
        ...
        ...

现在,我的主要问题是:我应该在go例程中启动log(req)函数吗?

func myHttpHandler(rw http.ResponseWriter, req *http.Request) {
    rw.WriteHeader(200)
    go func() { log(req) } ()
}

据我所知,在这种情况下,没有必要为每个http请求打开一个goroutine。

由于log(req)函数的当前操作主要是通过channel发送一些数据,因此该操作非常快捷。 唯一不快的时间-是channel阻塞了。 现在,如果channel阻塞,则必须意味着工作进程已阻塞。 而且由于工作人员永远在信道上侦听消息-如果工作人员被阻止,则意味着我的机器确实无法产生更快的输出(工作人员会执行您可以想象的一些I/O ,但这也非常快,因为I / O每分钟仅发生一次)。

此外,由于我有N工作程序,因此我用于从处理程序发送消息的channel将使用N缓冲,因此只有在所有N工作程序均被阻止的情况下,该channel才会阻塞。

这个对吗? 使用goroutine进行log(req)调用的利弊是什么? 该处理程序每​​秒接收多达1万个请求,我想为每个请求打开一个goroutine并不是一个好主意。

在这种情况下,没有必要为每个http请求打开一个goroutine。

当您使用net/http的Server时已经发生了。 您的处理程序将在自己的goroutine中被调用。

我想为每个请求打开一个goroutine不是一个好主意。

这也不是一个坏主意。 Go的运行时可以轻松处理数十万个goroutine。

但是,如果log阻塞,您可能会在等待接收完整HTTP响应并且仅执行rw.WriteHeader(200)的客户端上超时。

为了解决这个问题,您可以执行以下操作:

if cr, ok := rw.(io.Closer) {
    cr.Close()
}

将响应的Content-Length标头设置为0也是一个好主意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM