2011-12-27 25 views

Respuesta

11

El número de conexiones HTTP concurrentes está limitado por la memoria disponible y por los límites del sistema operativo.

En Linux, los límites del sistema operativo suave, como el número máximo de archivos abiertos, pueden imprimirse y modificarse usando ulimit.

En términos de memoria, cada conexión HTTP en un servidor Go HTTP mínimo que se ejecuta en Linux de 32 bits consume 21 KiB de memoria (el código fuente de este servidor, compilable con la versión Go 2013-03-23, es abajo). En Linux de 64 bits, se puede esperar que el consumo de memoria sea mayor.

En un sistema de 32 bits con 1GB de memoria disponible para el servidor, 21 KiB significa que aproximadamente 50,000 son posibles conexiones simultáneas. Esto no incluye memoria consumida por el kernel de 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) 
     } 
    } 
} 
+2

Debe tenerse en cuenta que, si bien todos los puertos son solo puertos, el grupo bajo se considera reservado. El impacto de jugar con algo por debajo de 1024 puede romper algo inesperado. Por ejemplo, ha abierto el puerto 80 para aceptar solicitudes, pero no puede aceptar ninguna porque está enviando datos desde allí. – Incognito

+0

De incógnito, me gustan tus comentarios, pero ¿puedes explicar un poco más? Es el 1024 en bytes o KB? Si envío solicitudes http desde un servidor Unix de 64 bits, ¿cuál es el máximo que puedo enviar al mismo tiempo? ¡Gracias! – trillions

+0

@Atom El código ya no se compila en go v1.0.3 a partir del 3/23/13. ¿Puedes arreglarlo? –

Cuestiones relacionadas