goroutine

传统语言的网络层处理

read()write()

上图中:

socket.accept()socketconnepollsocketepollepollreadwritewritewriteepollsocket

这种模型的编程难度主要体现在:

  1. 线程少(也不能太多),导致一个线程需要处理多个描述符,从而存在对描述符状态的维护问题。甚至,业务层面的会话等都需要小心维护
  2. 非阻塞IO调用,使描述符的状态更为复杂
  3. 队列的同步处理

不得不说,能用C或C++来写服务器的是真大神!

Golang的goroutine

GolangGolang协程goroutine
gogoroutine
func main() {
    log.Println("Hello, world")

    netListen, err := net.Listen("tcp", "localhost:4000")
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }

    defer netListen.Close()

    log.Println("Waiting for clients")

    for {
        conn, err := netListen.Accept()
        if err != nil {
            continue
        }

        log.Println(conn.RemoteAddr().String(), " tcp connect success")
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    ...
}

Golang的channel

channelchannelgoroutinegoroutinechannel

Golang如何实现网络层

goroutine

上图是单个客户端连接的服务器模块结构,同样的一个颜色代表一个协程:

goroutineacceptconngoroutine阻塞读goroutine阻塞写读channelgoroutinegoroutine写channelgoroutine
goroutine

再来看看多个客户端的情况:

goroutinegoroutinegoroutine