Go服务器的理论最大并发(同时)HTTP连接数是多少?

huangapple go评论79阅读模式
英文:

What is the theoretical max number of concurrent (simultaneous) HTTP connections in a Go server?

问题

非常简单的Go实现的服务器能够处理的并发HTTP连接数量的上限是多少?

英文:

What is the upper limit on the number of concurrent HTTP connections that a very simple server implemented in Go can handle?

答案1

得分: 17

并发HTTP连接的数量受可用内存和操作系统限制的限制。

在Linux中,软操作系统限制(如最大打开文件数)可以通过使用<code>ulimit</code>来打印和更改。

就内存而言,在运行在32位Linux上的最小Go HTTP服务器中,每个HTTP连接消耗21 KiB的内存(此服务器的源代码可使用Go版本2013-03-23进行编译,如下所示)。在64位Linux上,内存消耗可能会更高。

在具有1GB可用内存的32位系统上,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)
        }
    }
}
英文:

The number of concurrent HTTP connections is limited by available memory and by operating system limits.

In Linux, the soft operating system limits - such as the maximum number of open files - can be printed out and changed by using <code>ulimit</code>.

In terms of memory, each HTTP connection in a minimal Go HTTP server running on 32-bit Linux consumes 21 KiB of memory (the source code of this server, compilable with Go version 2013-03-23, is below). On 64-bit Linux, the memory consumption can be expected to be higher.

On a 32-bit system with 1GB of memory available to the server, 21 KiB means that about 50,000 simultaneous connections are possible. This does not include memory consumed by the Linux kernel.

package main

import (
    &quot;flag&quot;
    &quot;fmt&quot;
    &quot;net/http&quot;
    &quot;os&quot;
    &quot;runtime&quot;
    &quot;sync&quot;
)

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

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

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

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

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

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

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

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

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

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

huangapple
  • 本文由 发表于 2011年12月27日 22:40:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/8645836.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定