【问题标题】:Why is my webserver in golang not handling concurrent requests?为什么我在 golang 中的网络服务器不处理并发请求?
【发布时间】:2012-05-23 13:23:36
【问题描述】:

这个简单的 HTTP 服务器包含一个对 time.Sleep() 的调用,它使 每个请求需要五秒钟。当我尝试快速加载多个 浏览器中的选项卡,很明显每个请求 排队并按顺序处理。如何让它处理并发请求?

package main

import (
   "fmt"
   "net/http"
   "time"
)

func serve(w http.ResponseWriter, r *http.Request) {
   fmt.Fprintln(w, "Hello, world.")
   time.Sleep(5 * time.Second)
}

func main() {
   http.HandleFunc("/", serve)
   http.ListenAndServe(":1234", nil) 
}

其实我是在写完问题后才找到这个答案的,而且很微妙。无论如何我都会发布它,因为我在谷歌上找不到答案。你能看出我做错了什么吗?

【问题讨论】:

  • 你找到的答案是什么?
  • 问题出在我测试的方式上。 Web 浏览器限制了它们与任何一台服务器建立的连接数,即使在选项卡之间也是如此。
  • 您可能还想使用 jMeter 向您的服务器发出请求
  • 您还应该使用runtime.NumCPU() 看到您的CPU 编号,并使用runtime.GOMAXPROCS(numCPU) 设置它。如果 numCPU 等于 1,则不会发生并发,因为进程只会在一个 CPU 上执行。

标签: go


【解决方案1】:

您的程序已经同时处理请求。您可以使用 Apache 2 附带的基准测试工具 ab 对其进行测试:

ab -c 500 -n 500 http://localhost:1234/

在我的系统上,基准测试总共需要 5043 毫秒来处理所有 500 个并发请求。 只是您的浏览器限制了每个网站的连接数。

顺便说一句,对 Go 程序进行基准测试并不是那么容易,因为您需要确保您的基准测试工具不是瓶颈,并且它还能够处理那么多并发连接。因此,最好使用几台专用计算机来生成负载。

【讨论】:

  • 我想编辑你的答案,从最后一段中删除“Go”这个词……;-)
  • 我试图理解代码:我们是否暗示 http.HandleFunc() 会产生一个 goroutine 来处理请求并立即返回?
  • goroutines 生成得更早。 http.ListenAndServe 在无限循环中接受新连接并生成新的 goroutine 来处理它们。
  • 很高兴知道。我希望包文档和我在网上看到的许多示例能更清楚地说明这一点:-)
  • 您还应该使用runtime.NumCPU() 看到您的CPU 编号并使用runtime.GOMAXPROCS(numCPU) 设置它。如果 numCPU 等于 1,则不会发生并发,因为进程只会在一个 CPU 上执行。
【解决方案2】:

从 Server.go 开始,当连接被接受时,go 例程在 Serve 函数中生成。下面是sn-p,:-

// Serve accepts incoming connections on the Listener l, creating a 
// new service goroutine for each.  The service goroutines read requests and
// then call srv.Handler to reply to them.
func (srv *Server) Serve(l net.Listener) error {
        for {
            rw, e := l.Accept()
               if e != nil {
......
            c, err := srv.newConn(rw)
            if err != nil {
                continue
            }
            c.setState(c.rwc, StateNew) // before Serve can return
            go c.serve()
        }
}

【讨论】:

    【解决方案3】:

    如果您使用 xhr 请求,请确保 xhr 实例是局部变量。

    例如,xhr = new XMLHttpRequest() 是一个全局变量。当您使用相同的 xhr 变量执行并行请求时,您只会收到一个结果。所以,你必须像 var xhr = new XMLHttpRequest() 这样在本地声明 xhr。

    【讨论】:

      猜你喜欢
      • 2019-06-07
      • 2021-06-30
      • 2020-04-24
      • 2022-12-08
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      • 2013-10-02
      • 2015-08-08
      相关资源
      最近更新 更多