去,tcp太多打开的文件调试

这是一个简单的 Go http (tcp) 连接测试脚本


func main() {

    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        fmt.Fprintln(w, "Hello, client")

    }))

    defer ts.Close()

    var wg sync.WaitGroup

    for i := 0; i < 2000; i++ {

        wg.Add(1)

        go func(i int) {

            defer wg.Done()

            resp, err := http.Get(ts.URL)

            if err != nil {

                panic(err)

            }

            greeting, err := ioutil.ReadAll(resp.Body)

            resp.Body.Close()

            if err != nil {

                panic(err)

            }

            fmt.Printf("%s", i, greeting)

        }(i)

    }

    wg.Wait()

}

如果我在 Ubuntu 中运行它,我会得到:


panic: Get http://127.0.0.1:33202: dial tcp 127.0.0.1:33202: too many open files


其他帖子说要确保Close连接,我在这里做这一切。和其他人说增加最大连接的限制ulimit或尝试sudo sysctl -w fs.inotify.max_user_watches=100000但仍然不起作用。


如何在单个服务器中运行数百万个 tcp 连接 goroutines?它仅在 2,000 个连接时崩溃。


哔哔one
浏览 204回答 3
3回答

婷婷同学_

Go 的 http 包默认不指定请求超时。您应该始终在服务中包含超时。如果客户不关闭他们的会话怎么办?您的进程将保持活跃的旧会话达到 ulimits。一个坏演员可能会故意打开数千个会话,对您的服务器进行 DOS 攻击。重负载服务也应该调整 ulimits,但会调整 backstop 的超时时间。确保您指定超时:http.DefaultClient.Timeout&nbsp;=&nbsp;time.Minute&nbsp;*&nbsp;10您可以通过监控进程打开的文件前后验证:lsof&nbsp;-p&nbsp;[PID_ID]

摇曳的蔷薇

如果您想运行数百万个打开/读取/关闭套接字的 go 例程,那么您最好提高 ulimit,或者打开/读取/关闭套接字并将读取的值传递给 go-routine,但我会使用缓冲通道来控制您希望能够打开多少个文件描述符。const (&nbsp; &nbsp; // this is where you can specify how many maxFileDescriptors&nbsp; &nbsp; // you want to allow open&nbsp; &nbsp; maxFileDescriptors = 100)func main() {&nbsp; &nbsp; ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Fprintln(w, "Hello, client")&nbsp; &nbsp; }))&nbsp; &nbsp; defer ts.Close()&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; maxChan := make(chan bool, maxFileDescriptors)&nbsp; &nbsp; for i := 0; i < 1000; i++ {&nbsp; &nbsp; &nbsp; &nbsp; maxChan <- true&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(url string, i int, maxChan chan bool, wg *sync.WaitGroup) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer func(maxChan chan bool) { <-maxChan }(maxChan)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resp, err := http.Get(url)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; greeting, err := ioutil.ReadAll(resp.Body)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err = resp.Body.Close()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("%d: %s", i, string(greeting))&nbsp; &nbsp; &nbsp; &nbsp; }(ts.URL, i, maxChan, &wg)&nbsp; &nbsp; }&nbsp; &nbsp; wg.Wait()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go