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

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

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:

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

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

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

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:

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

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.

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

    1. func myHandler(w http.ResponseWriter, r *http.Request) {
    2. // handle request
    3. w.Write( ... )
    4. go func() {
    5. // Log the request, and send an email
    6. }()
    7. }

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:

确定