2012-05-23 13 views
47

Este servidor HTTP simple contiene una llamada a time.Sleep() que hace que cada solicitud tome cinco segundos. Cuando intento cargar rápidamente varias pestañas en un navegador, es obvio que cada solicitud se pone en cola y se maneja secuencialmente. ¿Cómo puedo hacer que maneje solicitudes simultáneas?¿Por qué mi servidor web en golang no maneja las solicitudes simultáneas?

package main 

import (
    "fmt" 
    "net/http" 
    "time" 
) 

func serve(w http.ResponseWriter, r *http.Request) { 
    fmt.Fprintln(w, "Hello, world.") 
    time.Sleep(5 * time.Second) 
} 

func main() { 
    http.HandleFunc("/", serve) 
    http.ListenAndServe(":1234", nil) 
} 

En realidad, acabo de encontrar la respuesta a esto después de escribir la pregunta, y es muy sutil. Lo estoy publicando de todos modos, porque no pude encontrar la respuesta en Google. ¿Puedes ver lo que estoy haciendo mal?

+0

¿Cuál es la respuesta que encontraste? –

+3

El problema estaba en la forma en que lo probé. Los navegadores web limitan el número de conexiones que hacen a cualquier servidor, incluso entre pestañas. –

+1

También es posible que desee utilizar jMeter para enviar solicitudes a su servidor –

Respuesta

84

Su programa ya maneja las solicitudes al mismo tiempo. Puede probarlo con ab, una herramienta de referencia que se incluye con Apache 2:

ab -c 500 -n 500 http://localhost:1234/ 

En mi sistema, el punto de referencia tiene un total de 5043ms para servir a todas las 500 solicitudes simultáneas. Es solo su navegador el que limita el número de conexiones por sitio web.

Benchmarking Go no es tan fácil por cierto, porque necesita asegurarse de que su herramienta de referencia no sea el cuello de botella y que también pueda manejar tantas conexiones concurrentes. Por lo tanto, es una buena idea usar un par de computadoras dedicadas para generar carga.

+24

Quiero editar su respuesta para eliminar la palabra "Ir" de ese último párrafo ... ;-) – Ashe

+1

Estoy tratando de entender el código: ¿implicamos que http. HandleFunc() genera un goroutine para manejar la solicitud y vuelve inmediatamente? – Eno

+9

Los goroutines se generan mucho antes. http.ListenAndServe acepta nuevas conexiones en un ciclo infinito y engendra nuevas rutinas para manejarlas. – tux21b

7

Desde Server.go, la rutina go se genera en la función Servir cuando se acepta una conexión. A continuación se muestra el fragmento,: -

// Serve accepts incoming connections on the Listener l, creating a 
// new service goroutine for each. The service goroutines read requests and 
// then call srv.Handler to reply to them. 
func (srv *Server) Serve(l net.Listener) error { 
     for { 
      rw, e := l.Accept() 
       if e != nil { 
...... 
      c, err := srv.newConn(rw) 
      if err != nil { 
       continue 
      } 
      c.setState(c.rwc, StateNew) // before Serve can return 
      go c.serve() 
     } 
} 
0

Si utiliza petición XHR, asegúrese de que esa instancia xhr es una variable local.

Por ejemplo, xhr = new XMLHttpRequest() es una variable global. Cuando haces una solicitud paralela con la misma variable xhr, recibes solo un resultado. Por lo tanto, debe declarar xhr localmente como este var xhr = new XMLHttpRequest().

Cuestiones relacionadas