Go中实现的非常简单的服务器可以处理的并发HTTP连接数的上限是多少?
答案 0 :(得分:12)
并发HTTP连接数受可用内存和操作系统限制的限制。
在Linux中,可以使用ulimit
打印和更改软操作系统限制(例如最大打开文件数)。
就内存而言,在32位Linux上运行的最小Go HTTP服务器中的每个HTTP连接消耗 21 KiB 内存(此服务器的源代码,可与Go版本2013-03一起使用) -23,在下面)。在64位Linux上,内存消耗可能会更高。
在服务器可用1GB内存的32位系统上,21 KiB意味着可以同时进行 50,000 连接。这 not 包含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)
}
}
}