goroutine很快在被请求时阻止了http服务器

goroutine sooblocked the http server when it was reqn uested

The following code will soon be blocked

In a device management function, by visiting the http REST ful interface to determine whether the device is online, 30s access to 1000 devices, the current program is roughly as follows to see the number of goroutine is not very high, but soon the program will not Move, cpu, memory is not occupied too high

package main

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

func a() {
    b()
    //.....
}

var bb = 0

func b() {
    fmt.Printf("b:%d
", bb)
    bb++
    resp, err := http.Get("http://www.baidu.com")
    if err == nil {
        resp.Body.Close()
    }
    //...
}
func c() {
    t := time.NewTicker(time.Second * 30)
    for {
        fmt.Printf("start time:%s
", time.Now().Format("15:04:05"))
        bb = 0
        for i := 0; i < 1000; i++ {
            go a()
            if i%11 == 0 {
                time.Sleep(time.Millisecond * 300)
                fmt.Printf("i:%d go:%d
", i, runtime.NumGoroutine())
            }
        }
        <-t.C
        fmt.Printf("over time:%s
", time.Now().Format("15:04:05"))
    }
}
func main() {
    go c()
    for {

    }
}

block

The following code will not block,This is why, hope to give me some advice, thank you

package main

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

func a() {
    b()
}

var bb = 0

func b() {
    fmt.Printf("b:%d
", bb)
    bb++
    resp, err := http.Get("http://www.baidu.com")
    if err == nil {
        resp.Body.Close()
    }

}

func main() {
    for {
        for {
        go b()
        time.Sleep(time.Millisecond * 10)
        fmt.Printf("go:%d
", runtime.NumGoroutine())
    }
}

no-block

I think there is no switching point.
the Go scheduler is non preemptive. (cooperative)
all goroutines must be cooperative of scheduling

func main() {
    go c()
    for {
        // it is not cooperative
    }
}



the Go scheduler can switch only at specific points.
specific points is I/O, chan, Sleep, Gosched

try below code on block example

func main() {
    go c()
    for {
        runtime.Gosched() // or time.Sleep(any)
    }
}


I hope this would help you