Каково теоретическое максимальное количество одновременных (одновременных) HTTP-соединений на сервере Go?

Каков верхний предел количества одновременных HTTP-соединений, с которыми может справиться очень простой сервер, реализованный в Go?

Ответ 1

Количество одновременных HTTP-соединений ограничено доступной памятью и ограничениями операционной системы.

В Linux ограничения на программную операционную систему, такие как максимальное количество открытых файлов, могут быть распечатаны и изменены с помощью ulimit.

В терминах памяти каждое HTTP-соединение на минимальном HTTP-сервере Go, работающем на 32-разрядной Linux, потребляет 21 KiB из памяти (исходный код этого сервера, скомпилированный с Go version 2013-03 -23, ниже). В 64-битном Linux можно ожидать, что потребление памяти будет выше.

В 32-разрядной системе с 1 ГБ памяти, доступной для сервера, 21 KiB означает, что возможно одновременное подключение 50 000. Это не включает память, потребляемую ядром Linux.

package main

import (
    "flag"
    "fmt"
    "net/http"
    "os"
    "runtime"
    "sync"
)

var isClient = flag.Bool("client", false, "Whether to start the HTTP server or the HTTP client")
var N = flag.Int("n", 1000, "Number of concurrent HTTP requests")

var wait = make(chan byte)
var counter = 0
var reachedN = make(chan byte)

func handler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "some text")
    counter++
    if counter == *N {
        reachedN <- 0
    }
    <-wait // Block this goroutine
}

func main() {
    flag.Parse()
    if *N <= 0 {
        fmt.Fprintf(os.Stderr, "invalid number of goroutines")
        os.Exit(1)
    }

    if *isClient {
        // Initiate N http connections
        var wg sync.WaitGroup
        for i := 0; i < *N; i++ {
            wg.Add(1)
            go func(ii int) {
                _, err := http.Get("http://127.0.0.1:12345")
                if err != nil {
                    fmt.Fprintf(os.Stderr, "client %d: %s\n", ii, err)
                    os.Exit(1)
                }
                wg.Done()
            }(i)
        }
        wg.Wait()
    } else {
        runtime.GOMAXPROCS(1) // No concurrency

        // Read MemStats
        var m0 runtime.MemStats
        runtime.ReadMemStats(&m0)

        go func() {
            <-reachedN // Wait until there are *N concurrent requests

            // Read MemStats
            var m1 runtime.MemStats
            runtime.ReadMemStats(&m1)

            fmt.Printf("Number of HTTP connections:        %d\n", *N)
            fmt.Printf("Memory consumption per connection: %.2f bytes\n", float64(m1.Sys-m0.Sys)/float64(*N))
            os.Exit(1)
        }()

        http.HandleFunc("/", handler)
        err := http.ListenAndServe(":12345", nil)
        if err != nil {
        fmt.Fprintf(os.Stderr, "server: %s\n", err)
            os.Exit(1)
        }
    }
}