2012-05-23 12 views
47

Ten prosty serwer HTTP zawiera wywołanie metody time.Sleep(), która powoduje, że każde żądanie trwa pięć sekund. Kiedy próbuję szybko ładować wiele zakładek w przeglądarce, oczywiste jest, że każde żądanie jest kolejkowane i obsługiwane sekwencyjnie. Jak mogę obsłużyć współbieżne żądania?Dlaczego mój serwer internetowy w golang nie obsługuje jednoczesnych żądań?

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) 
} 

Właściwie znalazłem odpowiedź na to pytanie po napisaniu pytania i jest bardzo subtelne. Mimo to publikuję, ponieważ nie mogłem znaleźć odpowiedzi w Google. Czy widzisz, co robię źle?

+0

Jaką otrzymałeś odpowiedź? –

+3

Problem polegał na sposobie, w jaki testowałem. Przeglądarki internetowe ograniczają liczbę połączeń do jednego serwera, nawet między kartami. –

+1

Możesz również użyć jMeter do wysłania żądania do serwera –

Odpowiedz

84

Twój program już obsługuje zgłoszenia jednocześnie. Można przetestować go z ab, benchmark narzędzie, które jest dostarczany z Apache 2:

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

W moim systemie, ceniony zajmuje łącznie 5043ms służyć wszystkim 500 jednoczesnych żądań. To tylko przeglądarka, która ogranicza liczbę połączeń na stronę.

Benchmarking Go programów nie jest tak łatwo przy okazji, ponieważ trzeba się upewnić, że narzędzie analizy porównawczej nie jest wąskim gardłem i że jest w stanie obsłużyć wiele jednoczesnych połączeń. Dlatego dobrym pomysłem jest użycie kilku dedykowanych komputerów do generowania obciążenia.

+24

Chcę edytować odpowiedź, aby usunąć słowo "Go" z tego ostatniego akapitu ... ;-) – Ashe

+1

Próbuję zrozumieć kod: czy sugerujemy, że http. HandleFunc() spawns goroutine do obsługi żądania, a więc zwraca natychmiast? – Eno

+9

Goryle są odradzane dużo wcześniej. http.ListenAndServe akceptuje nowe połączenia w nieskończonej pętli i spawnuje nowe goroutiny, aby je obsłużyć. – tux21b

7

Z Server.go rutynowa procedura spawn pojawia się w funkcji Serve, gdy połączenie jest akceptowane. Poniżej znajduje się opis: -

// 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

Jeśli używasz żądania xhr, upewnij się, że instancja xhr jest zmienną lokalną. Na przykład xhr = new XMLHttpRequest() jest zmienną globalną. Gdy wykonasz żądanie równoległe z tą samą zmienną xhr, otrzymasz tylko jeden wynik. Tak więc musisz zadeklarować xhr lokalnie, tak jak ten var xhr = new XMLHttpRequest().

Powiązane problemy