From ce1472df66f4f8d2474fedd1ed3b07d771341548 Mon Sep 17 00:00:00 2001 From: vesem Date: Sun, 26 Dec 2021 18:49:52 -0500 Subject: [PATCH] Cleanup, tested dockerfile and makefile --- Dockerfile | 10 +++++-- go.mod | 5 +++- go.sum | 2 ++ redisLoadTest.go | 77 ++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 75 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1f03a75..74735ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,11 @@ FROM golang:1.17.5-bullseye AS builder + +RUN mkdir /tmp/redisloadtest + +WORKDIR /tmp/redisloadtest + COPY go.mod . +COPY go.sum . COPY redisLoadTest.go . RUN set -ex \ @@ -17,11 +23,11 @@ RUN useradd ${USER} --home-dir ${HOME} WORKDIR /tmp # Copy the binary from the builder stage -COPY --from=builder ${FILENAME} ./ +COPY --from=builder /tmp/redisloadtest/${FILENAME} ./ RUN mv /tmp/${FILENAME} ${FILEPATH} \ && chown ${USER}:${USER} ${FILEPATH}${FILENAME} \ - && chmod 4555 ${FILENAME}${FILEPATH} \ + && chmod 4555 ${FILEPATH}${FILENAME} \ && rm -rf -- /tmp/* \ WORKDIR ${HOME} diff --git a/go.mod b/go.mod index b620a8d..8c56b8b 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module redis go 1.17 -require github.com/gomodule/redigo v1.8.6 +require ( + github.com/gomodule/redigo v1.8.6 + github.com/montanaflynn/stats v0.6.6 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index f7d767d..b911409 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gomodule/redigo v1.8.6 h1:h7kHSqUl2kxeaQtVslsfUCPJ1oz2pxcyzLy4zezIzPw= github.com/gomodule/redigo v1.8.6/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/redisLoadTest.go b/redisLoadTest.go index 57518c1..c9b85ae 100644 --- a/redisLoadTest.go +++ b/redisLoadTest.go @@ -1,18 +1,16 @@ package main import ( - "context" "flag" "fmt" "github.com/gomodule/redigo/redis" + "github.com/montanaflynn/stats" "math" "math/rand" "sync" "time" ) -var ctx = context.Background() - /** buildTestData iterates through a goroutine of setRedis to build test data into the redis db @param redisPtr connection to redis @@ -38,16 +36,30 @@ Then starts goroutines for getRedis at that interval @param rate int requests per second for the test @param keyMaxValue int max value to query the database and expect a return */ -func getRateTest(rdbPtr *redis.Conn, rate int, keyMaxValue int) { +func getRateTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Duration) { + var durationChannel chan bool x := int(math.Abs(60 / float64(rate) * 1000)) rateLimiter := time.Tick(time.Millisecond * time.Duration(x)) fmt.Println("Starting Test at", rateLimiter, "milliseconds per request...") - //todo add end to test + go func() { + for i := 0; i < int(duration); i++ { + <-time.Tick(time.Second) + } + durationChannel <- true + }() + end := false for { - <-rateLimiter - key := rand.Intn(keyMaxValue) - go getRedis(rdbPtr, key) + if end { + break + } + select { + case <-rateLimiter: + key := rand.Intn(keyMaxValue) + go getRedis(rdbPtr, key) + case <-durationChannel: + end = true + } } fmt.Println("Rate test concluded...") } @@ -58,15 +70,29 @@ getBurstTest starts goroutines for getRedis at the burstRateLimit per second @param rate int requests per second for the test @param keyMaxValue int max value to query the database and expect a return */ -func getBurstTest(rdbPtr *redis.Conn, rate int, keyMaxValue int) { +func getBurstTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Duration) { + var durationChannel chan bool burstRateLimiter := time.Tick(time.Second) - //todo add end to test + go func() { + for i := 0; i < int(duration); i++ { + <-time.Tick(time.Second) + } + durationChannel <- true + }() fmt.Println("Starting burst test at", rate, "requests per second...") + end := false for { - <-burstRateLimiter - for i := 0; i < rate; i++ { - key := rand.Intn(keyMaxValue) - go getRedis(rdbPtr, key) + if end { + break + } + select { + case <-burstRateLimiter: + for i := 0; i < rate; i++ { + key := rand.Intn(keyMaxValue) + go getRedis(rdbPtr, key) + } + case <-durationChannel: + end = true } } fmt.Println("Burst test concluded...") @@ -121,6 +147,22 @@ func newPool(host string) *redis.Pool { } } +func keepTotal(timesSlice *[]float64, timesChan chan float64, endChan chan bool) { + +} + +/** +getResponseTimes takes a list of ints and returns mean, stddev, 95p, 99p +Uses stats library to calculate mean, stddev, 95p, 99p +*/ +func getResponseTimes(times []float64) (float64, float64, float64, float64) { + mean, _ := stats.Mean(times) + stddev, _ := stats.StandardDeviation(times) + perc99, _ := stats.Percentile(times, 99.00) + perc95, _ := stats.Percentile(times, 95.00) + return mean, stddev, perc99, perc95 +} + func main() { hostPtr := flag.String("host", "", "Redis Server FQDN:port") //usernamePtr := flag.String("username", "", "Redis Server username") @@ -131,6 +173,7 @@ func main() { burstPtr := flag.Bool("burst", true, "Boolean burst test default true") //todo this should be off that same csv rather than an input maxEntriesPtr := flag.Int("dbEntries", 50000, "Test rate limit, default 50/sec") + testDurationPtr := flag.Int("duration", 60, "Duration of each test") host := *hostPtr //todo add username/password support @@ -141,6 +184,8 @@ func main() { rate := *ratePtr burst := *burstPtr keyMaxValue := *maxEntriesPtr + durationInt := *testDurationPtr + duration := time.Duration(time.Second * time.Duration(durationInt)) pool := newPool(host) client := pool.Get() @@ -149,9 +194,9 @@ func main() { if initializeDB { buildTestData(&client, 50000) } - getRateTest(&client, rate, keyMaxValue) + getRateTest(&client, rate, keyMaxValue, duration) if burst { - getBurstTest(&client, rate, keyMaxValue) + getBurstTest(&client, rate, keyMaxValue, duration) } fmt.Println("Tests completed...") }