背景
最近老代碼中遇到的一個問題,表現為:
- goroutine數量在高峰期上漲,上漲后平峰期將不下來。也就是goroutine泄露
- 使用pprof看,進程堵塞在chan
chan的使用經驗
- 在使用chan時,需要注意堵塞問題
- chan做為參數傳遞時,每個接收方都需要注意chan可能的堵塞(否則chan可能無法自動回收,導致gorutine無法結束)
- chan對應剩余buff為0時,則堵塞到有buffer, 或者超時
- chan應該總是和超時機制配合使用
示例代碼
package main
import (
"flag"
"log"
"net/http"
_ "net/http/pprof"
"time"
"fmt"
)
func demo (){
ch := make(chan int) //1
//ch := make(chan int, 1) //2
go func() { //寫chan
time.Sleep(2 * time.Second)
ch <- 0 //執行完成
}()
select {
case <-ch: //讀chan
fmt.Printf("exec success\n")
return
case <- time.After(1 *time.Second):
fmt.Printf("exec timeout\n")
return
}
}
func main() {
flag.Parse()
go func() {
log.Println(http.ListenAndServe("localhost:8080", nil))
}()
for i := 0; i < 400; i++ {
go demo()
}
fmt.Printf("sleep 1hour")
time.Sleep(60 * time.Minute)
}
可以使用http://localhost:8080/debug/pprof/goroutine?debug=1查看
上面代碼在(1)打開時,發生goroutine泄漏

上面代碼在(2) 打開時,未發生goroutine泄漏

