diff options
author | Matus Fabian <matfabia@cisco.com> | 2024-06-28 16:11:04 +0200 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2024-07-23 20:37:29 +0000 |
commit | 5c4c1b63b9ba4c7b0d6f72833a8d706792c8dd9d (patch) | |
tree | 8f65718e4b0d5a3cf562d877cc4f5efe9be75841 | |
parent | d086a3650eea95056e738e2cc5dc18ce6edc278b (diff) |
prom: concurrent connections fix
Type: fix
Change-Id: I57814edb735e9dac916f2e01de95ccfb739ce655
Signed-off-by: Matus Fabian <matfabia@cisco.com>
-rw-r--r-- | extras/hs-test/http_test.go | 35 | ||||
-rw-r--r-- | extras/hs-test/infra/hst_suite.go | 1 | ||||
-rw-r--r-- | src/plugins/prom/prom.c | 11 |
3 files changed, 42 insertions, 5 deletions
diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 29bd272fe99..2983ba38fa0 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -9,9 +9,11 @@ import ( "net/http" "net/http/httptrace" "os" + "sync" "time" . "fd.io/hs-test/infra" + . "github.com/onsi/ginkgo/v2" ) func init() { @@ -24,7 +26,7 @@ func init() { HttpStaticMacTimeTest, HttpStaticBuildInUrlGetVersionVerboseTest, HttpVersionNotSupportedTest, HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathTraversalTest, HttpUriDecodeTest, HttpHeadersTest, HttpStaticFileHandler) - RegisterNoTopoSoloTests(HttpStaticPromTest, HttpTpsTest, HttpTpsInterruptModeTest) + RegisterNoTopoSoloTests(HttpStaticPromTest, HttpTpsTest, HttpTpsInterruptModeTest, PromConcurrentConnections) } const wwwRootPath = "/tmp/www_root" @@ -203,6 +205,37 @@ func HttpStaticPromTest(s *NoTopoSuite) { _, err = io.ReadAll(resp.Body) } +func promReq(s *NoTopoSuite, url string, wg *sync.WaitGroup) { + defer GinkgoRecover() + defer wg.Done() + client := NewHttpClient() + req, err := http.NewRequest("GET", url, nil) + s.AssertNil(err, fmt.Sprint(err)) + resp, err := client.Do(req) + s.AssertNil(err, fmt.Sprint(err)) + defer resp.Body.Close() + s.AssertEqual(200, resp.StatusCode) + _, err = io.ReadAll(resp.Body) +} + +func PromConcurrentConnections(s *NoTopoSuite) { + vpp := s.GetContainerByName("vpp").VppInstance + serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString() + url := "http://" + serverAddress + ":80/stats.prom" + + s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers")) + s.Log(vpp.Vppctl("prom enable")) + time.Sleep(time.Second * 5) + + var wg sync.WaitGroup + for i := 0; i < 20; i++ { + wg.Add(1) + go promReq(s, url, &wg) + } + wg.Wait() + s.Log(vpp.Vppctl("show session verbose proto http")) +} + func HttpStaticFileHandler(s *NoTopoSuite) { content := "<http><body><p>Hello</p></body></http>" content2 := "<http><body><p>Page</p></body></http>" diff --git a/extras/hs-test/infra/hst_suite.go b/extras/hs-test/infra/hst_suite.go index 1f1d54b1b94..028ab0bef1f 100644 --- a/extras/hs-test/infra/hst_suite.go +++ b/extras/hs-test/infra/hst_suite.go @@ -565,6 +565,7 @@ runBenchmark creates Gomega's experiment with the passed-in name and samples the passing in suite context, experiment and your data. You can also instruct runBenchmark to run with multiple concurrent workers. +Note that if running in parallel Gomega returns from Sample when spins up all samples and does not wait until all finished. You can record multiple named measurements (float64 or duration) within passed-in callback. runBenchmark then produces report to show statistical distribution of measurements. */ diff --git a/src/plugins/prom/prom.c b/src/plugins/prom/prom.c index 76899a2fd12..475e98b1038 100644 --- a/src/plugins/prom/prom.c +++ b/src/plugins/prom/prom.c @@ -208,7 +208,7 @@ static uword prom_scraper_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f) { - uword *event_data = 0, event_type; + uword *event_data = 0, event_type, *sh_as_uword; prom_main_t *pm = &prom_main; hss_session_handle_t sh; f64 timeout = 10000.0; @@ -223,12 +223,15 @@ prom_scraper_process (vlib_main_t *vm, vlib_node_runtime_t *rt, /* timeout, do nothing */ break; case PROM_SCRAPER_EVT_RUN: - sh.as_u64 = event_data[0]; vec_reset_length (pm->stats); pm->stats = scrape_stats_segment (pm->stats, pm->stats_patterns, pm->used_only); - session_send_rpc_evt_to_thread_force (sh.thread_index, - send_data_to_hss_rpc, &sh); + vec_foreach (sh_as_uword, event_data) + { + sh.as_u64 = (u64) *sh_as_uword; + session_send_rpc_evt_to_thread_force ( + sh.thread_index, send_data_to_hss_rpc, sh_as_uword); + } pm->last_scrape = vlib_time_now (vm); break; default: |