Hi Kevin, That's been a very good guess. Disabling the keep alive on the server has made it to serve exactly the number of concurrent requests specified on the LimitListener. Thank you very much for your help. Now I have to do some work to better understand how all these concepts play together.
Cheers, Pablo On Wed, May 24, 2017 at 12:59 PM, Kevin Conway <kevinjacobcon...@gmail.com> wrote: > I'm speculating a bit here until I can dig back into the listener stack, > but at least one variable you can tweak is the connection keep alive. On > the surface, limit listener appears to gate on the socket accept call. I > feel it is an important distinction because it limits the listener and not > the request handler so we're ready taking about concurrent connections > rather than requests. > > The default client will reuse established connections as available. It's > possible you've found a poor interaction beetween connection pooling and > connection limiting. You might try running your experiment again with keep > alive disabled on your HTTP client. > > On Tue, May 23, 2017, 05:57 Pablo Rozas Larraondo < > p.rozas.larrao...@gmail.com> wrote: > >> Hi gophers, >> >> I'm using netutil.LimitListener to limit the number of concurrent >> requests that can be handled in a server to limit the memory usage of the >> service. I've noticed that when I send a bunch of requests it serves the >> number passed to the LimitListerner but after that it serves n-2 requests. >> I wonder what the problem might be, not a big deal but maybe there is some >> kind of problem in the library. >> >> Here is the code that I've created to test this problem: >> >> Server (waits 5 seconds before replying with concurrency limited to 10): >> package main >> >> import ( >> "golang.org/x/net/netutil" >> "log" >> "net" >> "net/http" >> "time" >> ) >> >> type fooHandler struct { >> } >> >> func (fh *fooHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { >> time.Sleep(5 * time.Second) >> w.Write([]byte("Done")) >> } >> >> func main() { >> lis, err := net.Listen("tcp", ":8080") >> if err != nil { >> log.Fatalf("failed to listen: %v", err) >> } >> lis = netutil.LimitListener(lis, 10) >> fH := &fooHandler{} >> >> s := &http.Server{ >> Handler: fH, >> ReadTimeout: 60 * time.Second, >> WriteTimeout: 60 * time.Second, >> MaxHeaderBytes: 1 << 20, >> } >> >> if err := s.Serve(lis); err != nil { >> log.Fatalf("failed to serve: %v", err) >> } >> } >> >> >> Client (Sends 40 concurrent requests to the server): >> package main >> >> import ( >> "fmt" >> "io/ioutil" >> "net/http" >> "sync" >> ) >> >> func Ask(wg *sync.WaitGroup, n int) { >> resp, err := http.Get("http://localhost:8080") >> if err != nil { >> return >> } >> defer resp.Body.Close() >> body, err := ioutil.ReadAll(resp.Body) >> fmt.Println(err, string(body), n) >> wg.Done() >> } >> func main() { >> wg := &sync.WaitGroup{} >> for i := 0; i < 40; i++ { >> wg.Add(1) >> go Ask(wg, i) >> } >> wg.Wait() >> } >> >> In this example I see 10 responses after the first 5 seconds and then 8 >> responses every five seconds. >> >> go version go1.8 darwin/amd64 >> >> Thanks, >> Pablo >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.