Why is my webserver in golang not handling concurrent requests?

Go

Go Problem Overview


This simple HTTP server contains a call to time.Sleep() that makes each request take five seconds. When I try quickly loading multiple tabs in a browser, it is obvious that each request is queued and handled sequentially. How can I make it handle concurrent requests?

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

Actually, I just found the answer to this after writing the question, and it is very subtle. I am posting it anyway, because I couldn't find the answer on Google. Can you see what I am doing wrong?

Go Solutions


Solution 1 - Go

Your program already handles the requests concurrently. You can test it with ab, a benchmark tool which is shipped with Apache 2:

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

On my system, the benchmark takes a total of 5043ms to serve all 500 concurrent requests. It's just your browser which limits the number of connections per website.

Benchmarking Go programs isn't that easy by the way, because you need to make sure that your benchmark tool isn't the bottleneck and that it is also able to handle that many concurrent connections. Therefore, it's a good idea to use a couple of dedicated computers to generate load.

Solution 2 - Go

From Server.go , the go routine is spawned in the Serve function when a connection is accepted. Below is the snippet, :-

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

Solution 3 - Go

If you use xhr request, make sure that xhr instance is a local variable.

For example, xhr = new XMLHttpRequest() is a global variable. When you do parallel request with the same xhr variable you receive only one result. So, you must declare xhr locally like this var xhr = new XMLHttpRequest().

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve HanovView Question on Stackoverflow
Solution 1 - Gotux21bView Answer on Stackoverflow
Solution 2 - GofactotumView Answer on Stackoverflow
Solution 3 - GoYassine ABIDView Answer on Stackoverflow