Created
August 23, 2016 14:08
-
-
Save klrkdekira/90be7ace5c0fb7f80b98ff60ed21579c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"sync" | |
) | |
type RobinHood struct { | |
counter int | |
mu *sync.Mutex | |
handlers []http.Handler | |
} | |
func (rh *RobinHood) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
rh.mu.Lock() | |
// Fail to do this will lock the server forever | |
defer rh.mu.Unlock() | |
rh.handlers[rh.counter].ServeHTTP(w, r) | |
rh.counter = (rh.counter + 1) % len(rh.handlers) | |
} | |
func (rh *RobinHood) AddHandler(handler http.Handler) { | |
rh.mu.Lock() | |
defer rh.mu.Unlock() | |
rh.handlers = append(rh.handlers, handler) | |
} | |
func newRobinHood(handlers ...http.Handler) *RobinHood { | |
return &RobinHood{ | |
counter: 0, | |
mu: &sync.Mutex{}, | |
handlers: handlers, | |
} | |
} | |
// boilerplate to create a closure Handler | |
func newHandler(msg string) http.Handler { | |
mux := http.NewServeMux() | |
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprintf(w, "Hello, from %s!", msg) | |
}) | |
return mux | |
} | |
func main() { | |
one := newHandler("One") | |
two := newHandler("Two") | |
three := newHandler("Three") | |
// Bootstrapping the handler | |
handler := newRobinHood(one, two, three) | |
server := &http.Server{ | |
Handler: handler, | |
Addr: "127.0.0.1:9090", | |
} | |
// Starts webserver in background | |
go func() { | |
if err := server.ListenAndServe(); err != nil { | |
log.Fatal(err) | |
} | |
}() | |
fmt.Println("Started web server") | |
// HTTP Request | |
req, err := http.NewRequest("GET", "http://127.0.0.1:9090/", nil) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Always close the connection | |
req.Close = true | |
requestCount := 5 | |
for i := 0; i < requestCount; i++ { | |
fmt.Printf("Calling server... (%d/%d)\n", i+1, requestCount) | |
lookup(req) | |
} | |
fmt.Println("Adding new handler") | |
handler.AddHandler(newHandler("Mystery Intruder")) | |
for i := 0; i < requestCount; i++ { | |
fmt.Printf("Calling server... (%d/%d)\n", i+1, requestCount) | |
lookup(req) | |
} | |
fmt.Println("All done, bye!") | |
} | |
func lookup(req *http.Request) { | |
resp, err := http.DefaultClient.Do(req) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Always close an io operation | |
defer resp.Body.Close() | |
b, err := ioutil.ReadAll(resp.Body) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Printf("Received response, %s\n", b) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ go run basic_http_round_robin_bonus.go | |
Started web server | |
Calling server... (1/5) | |
Received response, Hello, from One! | |
Calling server... (2/5) | |
Received response, Hello, from Two! | |
Calling server... (3/5) | |
Received response, Hello, from Three! | |
Calling server... (4/5) | |
Received response, Hello, from One! | |
Calling server... (5/5) | |
Received response, Hello, from Two! | |
Adding new handler | |
Calling server... (1/5) | |
Received response, Hello, from Three! | |
Calling server... (2/5) | |
Received response, Hello, from Mystery Intruder! | |
Calling server... (3/5) | |
Received response, Hello, from One! | |
Calling server... (4/5) | |
Received response, Hello, from Two! | |
Calling server... (5/5) | |
Received response, Hello, from Three! | |
All done, bye! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment