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

问题描述:

goroutine在请求http服务器时阻塞了它

以下代码将很快被阻止

在设备管理功能中,通过访问http REST ful接口来确定该设备是否在线,30s可以访问1000个设备,当前程序大致如下,看到goroutine的数量不是很高,但是很快程序不会移动,CPU,内存不会占用太高

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\n", 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\n", 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\n", i, runtime.NumGoroutine())
            }
        }
        <-t.C
        fmt.Printf("over time:%s\n", time.Now().Format("15:04:05"))
    }
}
func main() {
    go c()
    for {

    }
}

阻止

以下代码不会被阻止,这就是为什么,希望给我一些建议,谢谢

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\n", 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\n", runtime.NumGoroutine())
    }
}

无障碍

我认为没有切换点.
Go调度程序是非抢占式的. (合作)
所有goroutine必须配合调度

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
    }
}



Go调度程序只能在特定点切换.
具体点是I/O,chan,Sleep,Gosched



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