goroutine soon blocked the http server when it was requested

雨燕双飞 提交于 2019-12-24 23:15:30

问题


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\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 {

    }
}

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\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())
    }
}

no-block


回答1:


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



来源:https://stackoverflow.com/questions/46120712/goroutine-soon-blocked-the-http-server-when-it-was-requested

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!