Created
February 24, 2017 03:12
-
-
Save hackintoshrao/a856378dad60bd0b0890b2883aa08b59 to your computer and use it in GitHub Desktop.
Leaky server with the instrumentation for
This file contains hidden or 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" | |
| "log" | |
| "net/http" | |
| "runtime" | |
| "runtime/debug" | |
| "runtime/pprof" | |
| "strconv" | |
| ) | |
| // get the count of number of go routines in the system. | |
| func countGoRoutines() int { | |
| return runtime.NumGoroutine() | |
| } | |
| // respond with number of go routines in the system. | |
| func getGoroutinesCountHandler(w http.ResponseWriter, r *http.Request) { | |
| // Get the count of number of go routines running. | |
| count := countGoRoutines() | |
| w.Write([]byte(strconv.Itoa(count))) | |
| } | |
| // respond with the stack trace of the system. | |
| func getStackTraceHandler(w http.ResponseWriter, r *http.Request) { | |
| stack := debug.Stack() | |
| w.Write(stack) | |
| pprof.Lookup("goroutine").WriteTo(w, 2) | |
| } | |
| // function to add an array of numbers. | |
| func sum(s []int, c chan int) { | |
| sum := 0 | |
| for _, v := range s { | |
| sum += v | |
| } | |
| // writes the sum to the go routines. | |
| c <- sum // send sum to c | |
| } | |
| // HTTP handler for /sum | |
| func sumConcurrent(w http.ResponseWriter, r *http.Request) { | |
| s := []int{7, 2, 8, -9, 4, 0} | |
| c1 := make(chan int) | |
| c2 := make(chan int) | |
| // spin up a goroutine. | |
| go sum(s[:len(s)/2], c1) | |
| // spin up a goroutine. | |
| go sum(s[len(s)/2:], c2) | |
| // not reading from c2. | |
| // go routine writing to c2 will be blocked. | |
| x := <-c1 | |
| // write the response. | |
| fmt.Fprintf(w, strconv.Itoa(x)) | |
| } | |
| func main() { | |
| // get the sum of numbers. | |
| http.HandleFunc("/sum", sumConcurrent) | |
| // get the count of number of go routines in the system. | |
| http.HandleFunc("/_count", getGoroutinesCountHandler) | |
| // respond with the stack trace of the system. | |
| http.HandleFunc("/_stack", getStackTraceHandler) | |
| err := http.ListenAndServe(":8001", nil) | |
| if err != nil { | |
| log.Fatal("ListenAndServe: ", err) | |
| } | |
| } |
This file contains hidden or 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 ( | |
| "io/ioutil" | |
| "log" | |
| "net/http" | |
| "strconv" | |
| "sync" | |
| ) | |
| const ( | |
| leakyServer = "http://localhost:8001" | |
| ) | |
| // get the count of the number of go routines in the server. | |
| func getRoutineCount() (int, error) { | |
| body, err := getReq("/_count") | |
| if err != nil { | |
| return -1, err | |
| } | |
| count, err := strconv.Atoi(string(body)) | |
| if err != nil { | |
| return -1, err | |
| } | |
| return count, nil | |
| } | |
| // Send get request and return the repsonse body. | |
| func getReq(endPoint string) ([]byte, error) { | |
| response, err := http.Get(leakyServer + endPoint) | |
| if err != nil { | |
| return []byte{}, err | |
| } | |
| defer response.Body.Close() | |
| body, err := ioutil.ReadAll(response.Body) | |
| if err != nil { | |
| return []byte{}, err | |
| } | |
| return body, nil | |
| } | |
| // obtain stack trace of the server. | |
| func getStackTrace() (string, error) { | |
| body, err := getReq("/_stack") | |
| if err != nil { | |
| return "", err | |
| } | |
| return string(body), nil | |
| } | |
| func main() { | |
| // get the number of go routines in the leaky server. | |
| count, err := getRoutineCount() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| log.Printf("\n %d Go routines before the load test in the system.", count) | |
| var wg sync.WaitGroup | |
| // send 50 concurrent request to the leaky endpoint. | |
| for i := 0; i < 50; i++ { | |
| wg.Add(1) | |
| go func() { | |
| defer wg.Done() | |
| _, err = getReq("/sum") | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| }() | |
| } | |
| wg.Wait() | |
| // get the cout of number of goroutines in the system after the load test. | |
| count, err = getRoutineCount() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| log.Printf("\n %d Go routines after the load test in the system.", count) | |
| // obtain the stack trace of the system. | |
| trace, err := getStackTrace() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| log.Printf("\nStack trace after the load test : \n %s",trace) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment