协程空跑问题 ?
问题的发现:
周末在使用go 语言websocket做了一个简易的服务端,当时为了测试使用chrome多开tab与服务器端通信?又一时好奇想探索,到底服务端开启了多少携程的数量,使用了pprof观察服务端的资源消耗情况。大抵在一个wsHandler里面使用了4个携程来异步处理读写,使用两个channel进行读写数据的收发。观察到当我关闭浏览器tab窗口的时候,goroutine的数量竟然没有减少,进行了一些探究。
什么是协程空跑:
在父协程中开启子协程,父协程如果不阻塞,父协程执行完毕后,如果go的进程也可以说main协程没有结束,子协程如果还运行有任务还会继续执行,如果是个死循环?。go语言中,没有父子协程的概念,除了主协程其余协程都是平行概念。
危害性:
对于常驻服务,每次连接都会产生一些空跑的常驻进程,时间久了内存和cpu占用就是问题。
代码示例:
package main
import (
"fmt"
"net/http"
_ "net/http/pprof"
)
func main() {
http.HandleFunc("/",handler)
http.ListenAndServe(":8081",nil);
}
func handler(w http.ResponseWriter,r *http.Request) {
go test()
w.Write([]byte("Hello World"))
}
//三个空跑协程,每连接一次,都会生成三个空跑协程。
func test() {
go empty()
go empty()
go empty()
}
func empty() {
i:=0;
for {
fmt.Println("int---",i);
i++;
}
}
初始化状态4个协程
每连接一次增加3个协程
周末碰到典型错误:
func (conn *Connection) ReadLoop() {
fmt.Println(conn.WsConn.RemoteAddr())
for {
if _, data, err := conn.WsConn.ReadMessage(); err == nil {
select {
case conn.readChan <- data:
case <-conn.closeChan:
conn.CloseConnetion();
return; // not break not break not break
}
} else {
conn.CloseConnetion();
return; // not break not break not break
}
}
}
网友评论