No need for more than one client with internal concurrency
This commit is contained in:
18
main.go
18
main.go
@@ -4,7 +4,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -89,23 +88,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func attack(targets Targets, ordering string, rate uint, duration time.Duration, rep Reporter) {
|
func attack(targets Targets, ordering string, rate uint, duration time.Duration, rep Reporter) {
|
||||||
// Magic formula that assumes each client can
|
|
||||||
// sustain 200 RPS under normal circumstances
|
|
||||||
clients := make([]*Client, int(math.Ceil(float64(rate)/200.0)))
|
|
||||||
ratePerClient := rate / uint(len(clients))
|
|
||||||
for i := 0; i < len(clients); i++ {
|
|
||||||
clients[i] = NewClient(ratePerClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
hits := make(chan *http.Request, rate*uint((duration).Seconds()))
|
hits := make(chan *http.Request, rate*uint((duration).Seconds()))
|
||||||
defer close(hits)
|
defer close(hits)
|
||||||
for i, idxs := 0, targets.Iter(ordering); i < cap(hits); i++ {
|
|
||||||
hits <- targets[idxs[i%len(idxs)]]
|
|
||||||
}
|
|
||||||
responses := make(chan *Response, cap(hits))
|
responses := make(chan *Response, cap(hits))
|
||||||
defer close(responses)
|
defer close(responses)
|
||||||
for _, client := range clients {
|
client := NewClient(rate)
|
||||||
go client.Drill(hits, responses) // Attack!
|
go client.Drill(hits, responses) // Attack!
|
||||||
|
for i, idxs := 0, targets.Iter(ordering); i < cap(hits); i++ {
|
||||||
|
hits <- targets[idxs[i%len(idxs)]]
|
||||||
}
|
}
|
||||||
// Wait for all requests to finish
|
// Wait for all requests to finish
|
||||||
for i := 0; i < cap(responses); i++ {
|
for i := 0; i < cap(responses); i++ {
|
||||||
|
|||||||
10
main_test.go
10
main_test.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -20,8 +21,11 @@ func TestAttackRate(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
attack(targets, "random", 50, 1*time.Second, NewTextReporter())
|
rate := uint(5000)
|
||||||
if hits := atomic.LoadUint64(&hitCount); hits != 50 {
|
rep := NewTextReporter()
|
||||||
t.Fatalf("Wrong number of hits: want %d, got %d\n", 50, hits)
|
attack(targets, "random", rate, 1*time.Second, rep)
|
||||||
|
if hits := atomic.LoadUint64(&hitCount); uint(hits) != rate {
|
||||||
|
rep.Report(os.Stdout)
|
||||||
|
t.Fatalf("Wrong number of hits: want %d, got %d\n", rate, hits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user