深入剖析 Go 语言运行时:IO 轮询器
netpoller 概述
考虑一个基于 goroutine-per-connection 模型的 TCP echo server:
import (
"fmt"
"io"
"log"
"net"
)
func worker(conn net.Conn) {
defer conn.Close()
b := make([]byte, 512)
for {
size, err := conn.Read(b)
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
size, err = conn.Write(b[0:size])
if err != nil {
log.Fatal(err)
}
}
}
func main() {
listner, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listner.Accept()
if err != nil {
log.Fatal(err)
}
go worker(conn)
}
}从用户侧看,系统该调用阻塞 goroutine,Go scheduler 调度其他 goroutine。问题在于,goroutine 复用在线程上,如果 IO 系统调用(如read(2)/write(2))阻塞,直接阻塞 goroutine 所在线程,Go scheduler 将没有机会调度 goroutine!





