我们是否应该为每个异步请求运行一个goroutine,即使它们是从彼此派生的?

huangapple go评论90阅读模式
英文:

Shall we run a goroutine for every async request, even when they are spawned from each other?

问题

我正在使用Go语言开发一个Web应用程序,我知道在http包中,每个请求都在一个单独的goroutine中运行。现在,如果这个goroutine中的代码查询数据库,然后等待并使用数据库结果调用远程API来获取一些相关数据,以此类推,我应该将这些调用中的每一个都放在单独的goroutine中运行,还是使用http提供的那个goroutine就足够了?

英文:

I'm developing a web application in go and I know in http package, every request is run in a separate goroutine. Now, if the code inside this goroutine queries a database then wait and using db result calls a remote api to fetch some related data and son on and so forth, shall I run each of these calls in separate goroutine or the one provided by http is enough?

答案1

得分: 4

这取决于你在做什么。

每个HTTP请求应该按顺序处理。也就是说,你不应该为处理请求本身而启动一个goroutine:

func myHandler(w http.ResponseWriter, r *http.Request) {
    go func(w http.ResponseWriter, r *http.Request) {
        // 这样做没有优势
    }(w,r)
}

然而,在处理HTTP响应时,仍然有时候使用goroutines是有意义的。最常见的两种情况可能是:

  1. 你想要并行执行某些操作。
func myHandler(w http.ResponseWriter, r *http.Request) {
    wg := &sync.WaitGroup{}
    wg.Add(2)
    go func() {
        defer wg.Done()
        /* 查询远程API */
    }()
    go func() {
        defer wg.Done()
        /* 查询数据库 */
    }()
    wg.Wait()
    // 完成处理响应
}
  1. 你想要在响应HTTP请求后完成某些处理,这样网页客户端就不必等待。
func myHandler(w http.ResponseWriter, r *http.Request) {
    // 处理请求
    w.Write( ... )
    go func() {
        // 记录请求并发送电子邮件
    }()
}
英文:

That depends on what you're doing.

Each HTTP request should be handled sequentially. That is to say, you shouldn't fire off a goroutine for handling the request itself:

func myHandler(w http.ResponseWriter, r *http.Request) {
    go func(w http.ResponseWriter, r *http.Request) {
        // There's no advantage to this
    }(w,r)
}

However, there are still times when goroutines make sense when handling an HTTP response. The two most common situations are probably:

  1. You want to do something in parallel.

     func myHandler(w http.ResponseWriter, r *http.Request) {
         wg := &sync.WaitGroup{}
         wg.Add(2)
         go func() {
             defer wg.Done()
             /* query a remote API */
         }()
         go func() {
             defer wg.Done()
             /* query a database */
         }()
         wg.Wait()
         // finish handling the response
     }
    
  2. You want to finish handling something after responding to the HTTP request, so that the web client doesn't have to wait.

     func myHandler(w http.ResponseWriter, r *http.Request) {
         // handle request
         w.Write( ... )
         go func() {
             // Log the request, and send an email
         }()
     }
    

huangapple
  • 本文由 发表于 2017年4月29日 15:02:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/43692778.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定