Каков верхний предел количества одновременных 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)
}
}
}