Handle 1 million concurrent connections with 50 lines Go code

98 views
Skip to first unread message

Jack Li

unread,
Apr 6, 2022, 9:43:16 AM4/6/22
to golang-nuts
Hi group,

I am going through this page: https://studygolang.com/articles/22820 , It claims that the 50 lines of Go code handles 1 million concurrent connections from network clients, on 1 single server machine with a 4-Core CPU and 16G memory.

Does the package net already utilize IO Multiplexing internally, like epoll (epoll_create, epoll_ctl, epoll_wait)? So I can just use package net and gain the epoll ability automatically without calling epoll apis manually in Go?

Thanks

Server:
```
package main

import (
    "fmt"
    "net"
    "os"
    "time"
)

var array []byte = make([]byte, 10)

func checkError(err error, info string) (res bool) {

    if err != nil {
        fmt.Println(info + "  " + err.Error())
        return false
    }
    return true
}

func Handler(conn net.Conn) {
    for {
        _, err := conn.Write(array)
        if err != nil {
            return
        }
        time.Sleep(10 * time.Second)
    }
}

func main() {

    for i := 0; i < 10; i += 1 {
        array[i] = 'a'
    }

    service := ":8888"
    tcpAddr, _ := net.ResolveTCPAddr("tcp4", service)
    l, _ := net.ListenTCP("tcp", tcpAddr)

    for {
        conn, err := l.Accept()
        if err != nil {
            fmt.Printf("accept error, err=%s\n", err.Error())
            os.Exit(1)
        }
        go Handler(conn)
    }

}
```

Client:

```
package main

import (
    "flag"
    "fmt"
    "net"
    "os"
    "time"
)

var RemoteAddr *string
var ConcurNum *int
var LocalAddr *string

func init() {
    RemoteAddr = flag.String("remote-ip", "127.0.0.1", "ip addr of remote server")
    ConcurNum = flag.Int("concurrent-num", 100, "concurrent number of client")
    LocalAddr = flag.String("local-ip", "0.0.0.0", "ip addr of remote server")
}

func consume() {

    laddr := &net.TCPAddr{IP: net.ParseIP(*LocalAddr)}

    var dialer net.Dialer
    dialer.LocalAddr = laddr

    conn, err := dialer.Dial("tcp", *RemoteAddr+":8888")
    if err != nil {
        fmt.Println("dial failed:", err)
        os.Exit(1)
    }
    defer conn.Close()

    buffer := make([]byte, 512)

    for {
        _, err2 := conn.Read(buffer)
        if err2 != nil {
            fmt.Println("Read failed:", err2)
            return
        }

        //  fmt.Println("count:", n, "msg:", string(buffer))

    }

}

func main() {
    flag.Parse()
    for i := 0; i < *ConcurNum; i++ {
        go consume()
    }
    time.Sleep(3600 * time.Second)
}
```

Amnon

unread,
Apr 6, 2022, 10:04:18 AM4/6/22
to golang-nuts
Yes, the Go runtime does use epoll internally and schedules gorountines when their data is available. 
See https://github.com/golang/go/blob/17b2fb1b656a275906b5071c562439d50a27f167/src/runtime/netpoll_epoll.go
It does scale nicely and can handle tens of thousands or even hundreds of thousands of concurrent connections, without the "Thundering 
Herd" type behaviour which one would expect from such systems.
I have not tried it with millions of connection, but if you are interested, then run a test, but the consume side of your test will run out of ports.

Ian Lance Taylor

unread,
Apr 6, 2022, 10:04:51 AM4/6/22
to Jack Li, golang-nuts
On Wed, Apr 6, 2022 at 6:43 AM 'Jack Li' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> I am going through this page: https://studygolang.com/articles/22820 , It claims that the 50 lines of Go code handles 1 million concurrent connections from network clients, on 1 single server machine with a 4-Core CPU and 16G memory.
>
> Does the package net already utilize IO Multiplexing internally, like epoll (epoll_create, epoll_ctl, epoll_wait)? So I can just use package net and gain the epoll ability automatically without calling epoll apis manually in Go?

I didn't read your program, but, yes, the net package uses epoll
internally. There is no need to call epoll yourself.

Ian

Robert Engels

unread,
Apr 6, 2022, 10:36:48 AM4/6/22
to Jack Li, golang-nuts
Yes. Go uses “green threads” with its own scheduler and uses facilities like epoll under the covers. 

On Apr 6, 2022, at 8:43 AM, 'Jack Li' via golang-nuts <golan...@googlegroups.com> wrote:


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/tencent_BEE3D2499F3C9358D7A1CD7C88E0228C6D07%40qq.com.
Reply all
Reply to author
Forward
0 new messages