Why isn't this go HTTP server spawning a goroutine per request in Chrome 47?

tlovely :

Previously titled: How to spawn goroutine per HTTP request?

The code below is a simple HTTP server that echos the path back to the requester. I used it to test if the ListenAndServe method of the net/http package by default fires a goroutine to handle each request; which I discovered it doesn't. If I make three requests at the same time, the first takes 10 seconds to return, the second 20 (10 seconds after the first returns), and the third 30 seconds.

package main

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

func handler(w http.ResponseWriter, r *http.Request) {
  time.Sleep(10000 * time.Millisecond)
  fmt.Fprint(w, r.URL.Path)
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":8080", nil)
}

Basically what I want is the main goroutine to listen for an HTTP connection, then pass the reading of the request and the response to a handler spawned in another goroutine.

Could someone point me in the right direction for accomplishing this? Preferably using the net/http package in go.

UPDATE 12/21/15 08:46 AM MST

I conducted the same exact test you did using my web browser (chrome 47), five requests at the root of localhost:8080, and the results were roughly:

1st: 10 seconds
2nd: 20 seconds
3rd: 30 seconds
4th: 36 seconds     
5th: 38 seconds

So, hopefully, the folks who would otherwise down-vote my question would understand my confusion and why I made the assumption I did. I have no idea why I got the results I did on the 4th and 5th request.

I ran the same test using curl and had the same results as @tomasz.

I'm using go1.2.1.

UPDATE 12/21/15 02:08 PM MST

Per @tomasz's suggestion below, I retitled this question from "How to spawn goroutine per HTTP request" to "Why isn't this go HTTP server spawning a goroutine per request in Chrome 47?"

tomasz :

All is good, your handler is run in a separate routine for each request. Take a look at the source code of http.Server.Serve method. The last line in accepting loop says:

go c.serve()

The problem is probably with your testing. If you check the behaviour through the multiple tabs in browser the requests for matching URLs are probably queued instead of running them simultaneously (i.e. your client is not using "routines", not the server).

Try two different browsers or just use command line and, say, curl to test requests in parallel. For example (with some help from bash):

$ for i in {1..5}; do time curl localhost:8080 &; done
# after ignoring some mess...
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.013 total
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.014 total
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.012 total
curl localhost:8080  0.00s user 0.00s system 0% cpu 10.019 total

You server works like a charm.

Update

I can confirm this behaviour on Chrome 47, but also noticed you can open multiple tabs with, say, http://localhost:8080/test1, http://localhost:8080/test2 etc. and you will get expected results. That indicates there's indeed some queuing mechanism in Chrome for matching URLs.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why isn't the Response field of this HTTP Request being populated?

Why isn't an HTTP request being issued when the route changes?

why goroutine block main func in this http server?

Why isn't this goroutine run, even with a `time.Sleep`?

Goroutine already started in Go web server from request but client disconnects, is it possible for a web server to close that particular goroutine?

Why isn't this method promoted in Go?

Why isn't my Go Reader working?

Why isn't website receiving POST request?

Why isn't PHP sending POST request?

Why isn't the post request sending cookies?

Chrome Extension: Why Isn't It Working?

Why isn't Map subclassable in chrome/node?

Why isn't X2Go Server in the main Ubuntu repository?

Why isn't the request body showing up in the Kubernetes API server audit log?

Why isn't the proxy server isn’t responding in IE 11?

why doesn't this go code print anything with a goroutine

Why isn't my DHCP server working?

why isn't rsync copying files to the server

The HTTP request to the remote WebDriver server for URL - Chrome

If an IP is not listening on HTTP (isn't a server) or is offline, does the GET request parameters still get sent over the wire to them?

HTTP header is being sent, but isn't present in Request.Headers

APM Go Agent isn't Sending Data to the APM Server

Go isn't detecting SOMAXCONN changes from aws ubuntu server

Why isn't Go 1.6.2 searching vendor/ for packages?

Why isn't Gcloud installing the "app-engine-go" component?

Why isn't short variable declaration allowed at package level in Go?

In Go, why isn't the stringer interface used when casting to string?

Webpack-dev-server isn't allowing CORS request

POST-ing JSON request to FCM server isn't working