From 17bf329e32ddbd53d11da89a219feedecb2519cc Mon Sep 17 00:00:00 2001 From: sgaluzin Date: Tue, 12 Sep 2023 00:50:09 +0300 Subject: [PATCH 1/3] Possibility to get services hosts list from eurekaAPI --- eurekaUrlsProvider/eurekaUrlsProvider.go | 92 ++++++++++++++++++++++++ main.go | 11 ++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 eurekaUrlsProvider/eurekaUrlsProvider.go diff --git a/eurekaUrlsProvider/eurekaUrlsProvider.go b/eurekaUrlsProvider/eurekaUrlsProvider.go new file mode 100644 index 0000000..7611916 --- /dev/null +++ b/eurekaUrlsProvider/eurekaUrlsProvider.go @@ -0,0 +1,92 @@ +package eurekaurlsprovider + +import ( + "encoding/xml" + "fmt" + "io" + "net/http" + "net/url" + "strings" +) + +type Applications struct { + XMLName xml.Name `xml:"applications"` + Applications []Application `xml:"application"` +} +type Application struct { + XMLName xml.Name `xml:"application"` + Name string `xml:"name"` + Instance Instance `xml:"instance"` +} +type Instance struct { + XMLName xml.Name `xml:"instance"` + App string `xml:"app"` + HostName string `xml:"hostName"` + IpAddr string `xml:"ipAddr"` + Status string `xml:"status"` + Port Port `xml:"port"` + SecurePort SecurePort `xml:"securePort"` +} + +type Port struct { + XMLName xml.Name `xml:"port"` + Enabled bool `xml:"enabled,attr"` + PortValue string `xml:",innerxml"` +} + +type SecurePort struct { + XMLName xml.Name `xml:"securePort"` + Enabled bool `xml:"enabled,attr"` + PortValue string `xml:",innerxml"` +} + +func LoadEurekaURLs(urldest string, eurekaService string) []*url.URL { + var urls []*url.URL + resp, err := http.Get(urldest) + + if err != nil { + panic(err) + } + + b, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + + defer resp.Body.Close() + + var applications Applications + err = xml.Unmarshal(b, &applications) + if err != nil { + fmt.Println(err) + panic(err) + } + + for i := 0; i < len(applications.Applications); i++ { + if strings.Contains(applications.Applications[i].Name, eurekaService) { + rawUrl := applications.Applications[i].Instance.HostName + if !strings.HasPrefix(rawUrl, "http") { + if applications.Applications[i].Instance.Port.Enabled { + rawUrl = "http://" + rawUrl + } else if applications.Applications[i].Instance.SecurePort.Enabled { + rawUrl = "https://" + rawUrl + } + } + + if applications.Applications[i].Instance.Port.Enabled { + rawUrl = rawUrl + ":" + applications.Applications[i].Instance.Port.PortValue + } else if applications.Applications[i].Instance.SecurePort.Enabled { + rawUrl = rawUrl + ":" + applications.Applications[i].Instance.SecurePort.PortValue + } + + URL, err := url.Parse(rawUrl) + if err != nil { + panic(err) + } + + urls = append(urls, URL) + } + } + + return urls +} diff --git a/main.go b/main.go index e99085e..902440e 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,7 @@ import ( "syscall" "time" + eurekaurlsprovider "github.com/buoyantio/slow_cooker/eurekaUrlsProvider" "github.com/buoyantio/slow_cooker/hdrreport" "github.com/buoyantio/slow_cooker/ring" "github.com/buoyantio/slow_cooker/window" @@ -322,6 +323,8 @@ func main() { metricAddr := flag.String("metric-addr", "", "address to serve metrics on") hashValue := flag.Uint64("hashValue", 0, "fnv-1a hash value to check the request body against") hashSampleRate := flag.Float64("hashSampleRate", 0.0, "Sampe Rate for checking request body's hash. Interval in the range of [0.0, 1.0]") + useEureka := flag.Bool("useEureka", false, "Eureka will be used for getting urls list by a specific service") + eurekaService := flag.String("eurekaService", "", "Specify service from Eureka's list for testing. % may be used as wildcard") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n", path.Base(os.Args[0])) @@ -340,7 +343,13 @@ func main() { } urldest := flag.Arg(0) - dstURLs := loadURLs(urldest) + + var dstURLs []*url.URL + if *useEureka { + dstURLs = eurekaurlsprovider.LoadEurekaURLs(urldest, *eurekaService) + } else { + dstURLs = loadURLs(urldest) + } if *qps < 1 { exUsage("qps must be at least 1") From e2e4e1d441da90814f572e289de247e9e3c2ba80 Mon Sep 17 00:00:00 2001 From: sgaluzin Date: Sun, 17 Sep 2023 21:28:13 +0300 Subject: [PATCH 2/3] fix frequency of requests for each url from urls list --- main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index 902440e..6d9c002 100644 --- a/main.go +++ b/main.go @@ -416,10 +416,8 @@ func main() { } fmt.Printf("# %s iter good/b/f t goal%% %s min [p50 p95 p99 p999] max bhash change\n", timePadding, intPadding) - stride := *concurrency - if stride > len(dstURLs) { - stride = 1 - } + + callTimes := make([]int, len(dstURLs)) for i := 0; i < *concurrency; i++ { ticker := time.NewTicker(timeToWait) go func(offset int) { @@ -438,15 +436,16 @@ func main() { shouldFinishLock.RLock() if !shouldFinish { shouldFinishLock.RUnlock() + callTimes[y]++ sendRequest(client, *method, dstURLs[y], hosts[rand.Intn(len(hosts))], headers, requestData, atomic.AddUint64(&reqID, 1), *noreuse, *hashValue, checkHash, hasher, received, bodyBuffer) } else { shouldFinishLock.RUnlock() sendTraffic.Done() return } - y += stride + y++ if y >= len(dstURLs) { - y = offset + y = 0 } } }(i % len(dstURLs)) @@ -484,6 +483,7 @@ func main() { // Don't Wait() in the event loop or else we'll block the workers // from draining. sendTraffic.Wait() + fmt.Println(callTimes) os.Exit(0) }() case t := <-timeout: From bade07e752cff7b2749ca047e74495ccb6ae4752 Mon Sep 17 00:00:00 2001 From: sgaluzin Date: Wed, 29 Nov 2023 00:39:19 +0300 Subject: [PATCH 3/3] Possibility to set extra uri if useEureka is enabled --- README.md | 3 +++ eurekaUrlsProvider/eurekaUrlsProvider.go | 4 ++-- main.go | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 61d19d4..d18066d 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,9 @@ or: | `-reportLatenciesCSV` | `` | Filename to write CSV latency values. Format of CSV is millisecond buckets with number of requests in each bucket. | | `-timeout` | 10s | Individual request timeout. | | `-totalRequests` | `` | Exit after sending this many requests. | +| `-useEureka ` | `` | If set, slow_cooker will try to get data from EurekaAPI by url argument.| +| `-eurekaService ` | `` | If set, slow_cooker will filter instances list by app tag.| +| `-eurekaExtraUri ` | `` | If set, slow_cooker will append it to url from EurekaAPI.| | `-help` | `` | If set, print all available flags and exit. | # Using a URL file diff --git a/eurekaUrlsProvider/eurekaUrlsProvider.go b/eurekaUrlsProvider/eurekaUrlsProvider.go index 7611916..40f8165 100644 --- a/eurekaUrlsProvider/eurekaUrlsProvider.go +++ b/eurekaUrlsProvider/eurekaUrlsProvider.go @@ -40,7 +40,7 @@ type SecurePort struct { PortValue string `xml:",innerxml"` } -func LoadEurekaURLs(urldest string, eurekaService string) []*url.URL { +func LoadEurekaURLs(urldest string, eurekaService string, eurekaExtraUri string) []*url.URL { var urls []*url.URL resp, err := http.Get(urldest) @@ -79,7 +79,7 @@ func LoadEurekaURLs(urldest string, eurekaService string) []*url.URL { rawUrl = rawUrl + ":" + applications.Applications[i].Instance.SecurePort.PortValue } - URL, err := url.Parse(rawUrl) + URL, err := url.Parse(rawUrl + eurekaExtraUri) if err != nil { panic(err) } diff --git a/main.go b/main.go index 6d9c002..17c3436 100644 --- a/main.go +++ b/main.go @@ -325,6 +325,7 @@ func main() { hashSampleRate := flag.Float64("hashSampleRate", 0.0, "Sampe Rate for checking request body's hash. Interval in the range of [0.0, 1.0]") useEureka := flag.Bool("useEureka", false, "Eureka will be used for getting urls list by a specific service") eurekaService := flag.String("eurekaService", "", "Specify service from Eureka's list for testing. % may be used as wildcard") + eurekaExtraUri := flag.String("eurekaExtraUri", "", "If set, slow_cooker will append it to url from EurekaAPI.") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n", path.Base(os.Args[0])) @@ -346,7 +347,7 @@ func main() { var dstURLs []*url.URL if *useEureka { - dstURLs = eurekaurlsprovider.LoadEurekaURLs(urldest, *eurekaService) + dstURLs = eurekaurlsprovider.LoadEurekaURLs(urldest, *eurekaService, *eurekaExtraUri) } else { dstURLs = loadURLs(urldest) } @@ -483,7 +484,6 @@ func main() { // Don't Wait() in the event loop or else we'll block the workers // from draining. sendTraffic.Wait() - fmt.Println(callTimes) os.Exit(0) }() case t := <-timeout: