Skip to content

Instantly share code, notes, and snippets.

@xeoncross
Created January 2, 2019 18:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xeoncross/4b169c7348bd5bce601b1fa8e30ce679 to your computer and use it in GitHub Desktop.
Save xeoncross/4b169c7348bd5bce601b1fa8e30ce679 to your computer and use it in GitHub Desktop.
Golang HTTP concurrency limiter / throttle for limiting the maximum number of concurrent http handlers running at one time.
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
"sync/atomic"
"time"
)
var requestsPerMinute uint64
func main() {
go func() {
for {
select {
case <-time.After(time.Second):
num := atomic.SwapUint64(&requestsPerMinute, 0)
fmt.Printf("%10d requests\n", num)
}
}
}()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
atomic.AddUint64(&requestsPerMinute, 1)
time.Sleep(time.Second)
w.Write([]byte("Hello World"))
})
http.Handle("/", Throttle(handler, 200))
// You could also use Throttle/Throttler on a mux to limit all endpoints
http.ListenAndServe(":8080", nil)
}
// Throttle one http.Handler
func Throttle(h http.Handler, n int) http.Handler {
sema := make(chan struct{}, n)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sema <- struct{}{}
h.ServeHTTP(w, r)
<-sema
})
}
// Throttler creates a re-usable limiter for multiple http.Handlers
func Throttler(n int) func(http.Handler) http.Handler {
sema := make(chan struct{}, n)
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sema <- struct{}{}
h.ServeHTTP(w, r)
<-sema
})
}
}
@xeoncross
Copy link
Author

echo "GET http://localhost:8080/" | vegeta attack -duration=10s -rate 1000 | vegeta report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment