为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
哔哔one 2021-11-01 17:16:53
这是一个简单的 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 个连接时崩溃。
查看完整描述

3 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

Go 的 http 包默认不指定请求超时。您应该始终在服务中包含超时。如果客户不关闭他们的会话怎么办?您的进程将保持活跃的旧会话达到 ulimits。一个坏演员可能会故意打开数千个会话,对您的服务器进行 DOS 攻击。重负载服务也应该调整 ulimits,但会调整 backstop 的超时时间。

确保您指定超时:

http.DefaultClient.Timeout = time.Minute * 10

您可以通过监控进程打开的文件前后验证:

lsof -p [PID_ID]


查看完整回答
反对 回复 2021-11-01
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

如果您想运行数百万个打开/读取/关闭套接字的 go 例程,那么您最好提高 ulimit,或者打开/读取/关闭套接字并将读取的值传递给 go-routine,但我会使用缓冲通道来控制您希望能够打开多少个文件描述符。


const (

    // this is where you can specify how many maxFileDescriptors

    // you want to allow open

    maxFileDescriptors = 100

)


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

    maxChan := make(chan bool, maxFileDescriptors)

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

        maxChan <- true

        wg.Add(1)

        go func(url string, i int, maxChan chan bool, wg *sync.WaitGroup) {

            defer wg.Done()

            defer func(maxChan chan bool) { <-maxChan }(maxChan)

            resp, err := http.Get(url)

            if err != nil {

                panic(err)

            }

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

            if err != nil {

                panic(err)

            }

            err = resp.Body.Close()

            if err != nil {

                panic(err)

            }

            fmt.Printf("%d: %s", i, string(greeting))

        }(ts.URL, i, maxChan, &wg)

    }

    wg.Wait()

}


查看完整回答
反对 回复 2021-11-01
  • 3 回答
  • 0 关注
  • 192 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信