From 18423fe6c1baac67c0f05832f628a8f35fe11cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Felipe=20Gon=C3=A7alves?= Date: Fri, 21 Jun 2024 21:18:42 -0300 Subject: [PATCH] wip --- cli/src/main.rs | 4 +- flake.nix | 2 + proto/src/clients/ctl.rs | 4 +- tests/perf-analysis/README.md | 45 ++++++++++ .../single-node/docker-compose.yml | 1 - tests/perf-analysis/test.js | 89 ++++++++++++------- .../tuc-multi-node/docker-compose.yml | 51 +++++++++++ tucano | 2 +- worker/src/args.rs | 4 +- worker/src/main.rs | 2 +- 10 files changed, 162 insertions(+), 42 deletions(-) create mode 100644 tests/perf-analysis/README.md create mode 100644 tests/perf-analysis/tuc-multi-node/docker-compose.yml diff --git a/cli/src/main.rs b/cli/src/main.rs index b9d65c0..506ecb3 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -13,7 +13,7 @@ pub struct Cli { #[command(subcommand)] cmd: Cmd, #[arg(short, long)] - ctl_addr: IpAddr, + ctl_addr: String, } #[derive(Debug, Subcommand)] @@ -67,7 +67,7 @@ pub enum ServiceCmd { #[tokio::main] async fn main() -> eyre::Result<()> { let cli = Cli::parse(); - let ctl_client = CtlClient::new(cli.ctl_addr); + let ctl_client = CtlClient::new(&cli.ctl_addr); match cli.cmd { Cmd::Node(cmd) => handle_node(cmd, ctl_client).await?, Cmd::Service(cmd) => handle_service(cmd, ctl_client).await?, diff --git a/flake.nix b/flake.nix index 8272b8a..605687c 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,8 @@ llvmPackages_16.llvm llvmPackages_16.bintools libiconv + + k6 ]; darwinPackages = lib.optionals isDarwin (with pkgs.darwin.apple_sdk.frameworks; [ CoreFoundation diff --git a/proto/src/clients/ctl.rs b/proto/src/clients/ctl.rs index 7a209be..8dfa737 100644 --- a/proto/src/clients/ctl.rs +++ b/proto/src/clients/ctl.rs @@ -1,4 +1,4 @@ -use std::{net::IpAddr, sync::Arc}; +use std::sync::Arc; use chrono::{DateTime, Utc}; @@ -30,7 +30,7 @@ pub struct CtlClient { impl CtlClient { #[must_use] - pub fn new(ctl_addr: IpAddr) -> Self { + pub fn new(ctl_addr: &str) -> Self { let base_url = format!("http://{ctl_addr}:{CTL_HTTP_PORT}") .into_boxed_str() .into(); diff --git a/tests/perf-analysis/README.md b/tests/perf-analysis/README.md new file mode 100644 index 0000000..e50517b --- /dev/null +++ b/tests/perf-analysis/README.md @@ -0,0 +1,45 @@ +# Pre-steps + +Build the image + +```bash +docker image build -t lffg/number-fact:latest ./tests/containers/number-fact +``` + +# Single node + +Start: + +```bash +docker compose -f ./tests/perf-analysis/single-node/docker-compose.yml up +``` + +In another terminal session: + +```bash +k6 run ./tests/perf-analysis/test.js +``` + +# Tucano multi node + +```bash +docker compose -f ./tests/perf-analysis/tuc-multi-node/docker-compose.yml up +``` + +Ensure that ctl log shows that 3 worker nodes joined the cluster. + +Deploy the application: + +```bash +./tucano -c localhost service deploy --id="number-fact" --image="lffg/number-fact" --public --concurrency="1" +``` + +Ensure that all deployments went right. + +In another terminal session: + +```bash +k6 run ./tests/perf-analysis/test.js +``` + +# Tucano multi node (4x) diff --git a/tests/perf-analysis/single-node/docker-compose.yml b/tests/perf-analysis/single-node/docker-compose.yml index 7178e7b..7971ada 100644 --- a/tests/perf-analysis/single-node/docker-compose.yml +++ b/tests/perf-analysis/single-node/docker-compose.yml @@ -1,7 +1,6 @@ services: server01: build: ../../containers/number-fact - hostname: html1 networks: - tucano-cluster-net ports: diff --git a/tests/perf-analysis/test.js b/tests/perf-analysis/test.js index 058ce22..414dfc1 100644 --- a/tests/perf-analysis/test.js +++ b/tests/perf-analysis/test.js @@ -1,66 +1,86 @@ // k6 run ./test.js -import http from 'k6/http'; -import { check, sleep } from 'k6'; -import { Trend } from 'k6/metrics'; +import http from "k6/http"; +import { check, sleep } from "k6"; +import { Trend } from "k6/metrics"; -const API_URL = 'http://localhost:8080/factors'; +const API_URL = "http://localhost:8080/factors"; -const easyResponseTimes = new Trend('easy_response_times', true); -const mediumResponseTimes = new Trend('medium_response_times', true); -const hardResponseTimes = new Trend('hard_response_times', true); +const easyResponseTimes = new Trend("easy_response_times", true); +const mediumResponseTimes = new Trend("medium_response_times", true); +const hardResponseTimes = new Trend("hard_response_times", true); export const options = { scenarios: { easyNumbers: { - executor: 'constant-vus', + executor: "constant-vus", vus: 8, - duration: '30s', - exec: 'easyNumbers', + duration: "30s", + exec: "easyNumbers", }, mediumNumbers: { - executor: 'constant-vus', + executor: "constant-vus", vus: 8, - duration: '30s', - exec: 'mediumNumbers', - startTime: '30s', + duration: "30s", + exec: "mediumNumbers", + startTime: "30s", }, hardNumbers: { - executor: 'constant-vus', + executor: "constant-vus", vus: 8, - duration: '30s', - exec: 'hardNumbers', - startTime: '60s', + duration: "30s", + exec: "hardNumbers", + startTime: "60s", }, }, }; export function easyNumbers() { const numbers = [ - '12345', '67890', '111213', '141516', '171819', - '202122', '232425', '262728', '293031', '323334' + "12345", + "67890", + "111213", + "141516", + "171819", + "202122", + "232425", + "262728", + "293031", + "323334", ]; - testAPI(numbers, 'easy'); + testAPI(numbers, "easy"); } export function mediumNumbers() { const numbers = [ - '12345678901234567890', '98765432109876543210', '11223344556677889900', - '99887766554433221100', '10203040506070809000', '50607080901020304050', - '21436587092143658709', '13579246801357924680', '98765412309876541230', - '19283746501928374650' + "12345678901234567890", + "98765432109876543210", + "11223344556677889900", + "99887766554433221100", + "10203040506070809000", + "50607080901020304050", + "21436587092143658709", + "13579246801357924680", + "98765412309876541230", + "19283746501928374650", ]; - testAPI(numbers, 'medium'); + testAPI(numbers, "medium"); } export function hardNumbers() { const numbers = [ - '123456789012345677777', '987654321098765432777', '112233445566778899075', - '998877665544332211057', '102030405060708090057', '506070809010203040575', - '214365870921436587577', '135792468013579246875', '9876541230987654123775', - '19283746501928374655705' + "123456789012345677777", + "987654321098765432777", + "112233445566778899075", + "998877665544332211057", + "102030405060708090057", + "506070809010203040575", + "214365870921436587577", + "135792468013579246875", + "9876541230987654123775", + "19283746501928374655705", ]; - testAPI(numbers, 'hard'); + testAPI(numbers, "hard"); } function testAPI(numbers, tag) { @@ -72,15 +92,18 @@ function testAPI(numbers, tag) { for (const number of numbers) { const res = http.get(`${API_URL}?number=${number}`, { + headers: { + Host: "number-fact", + }, tags: { scenario: tag }, }); check(res, { - 'status is 200': (r) => r.status === 200, + "status is 200": (r) => r.status === 200, }); trends[tag].add(res.timings.duration); - sleep(1); + sleep(1); } } diff --git a/tests/perf-analysis/tuc-multi-node/docker-compose.yml b/tests/perf-analysis/tuc-multi-node/docker-compose.yml new file mode 100644 index 0000000..9b04fbc --- /dev/null +++ b/tests/perf-analysis/tuc-multi-node/docker-compose.yml @@ -0,0 +1,51 @@ +services: + ctl: + build: + context: ../../.. # repo root + dockerfile: ./dockerfiles/node.dockerfile + args: + CRATE: ctl + entrypoint: + - /usr/local/bin/ctl + networks: [tucano-cluster-net] + ports: + - "8080:8080" # balancer + - "7070:7070" # http + environment: + RUST_LOG: info,ctl=trace + deploy: + resources: + limits: + cpus: "0.25" + memory: "128MB" + + worker1: &w1 + depends_on: [ctl] + build: + context: ../../.. # repo root + dockerfile: ./dockerfiles/node.dockerfile + args: + CRATE: worker + entrypoint: + - /usr/local/bin/worker + - -c=ctl + networks: + - tucano-cluster-net + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + RUST_LOG: info,worker=trace + deploy: + resources: + limits: + cpus: "0.25" + memory: "128MB" + + worker2: + <<: *w1 + worker3: + <<: *w1 + +networks: + tucano-cluster-net: + attachable: true diff --git a/tucano b/tucano index fb0e7cd..80dc594 100755 --- a/tucano +++ b/tucano @@ -1,4 +1,4 @@ #!/usr/bin/env bash -cargo build -q +cargo build ./target/debug/cli "$@" diff --git a/worker/src/args.rs b/worker/src/args.rs index b2a7e3a..607c02a 100644 --- a/worker/src/args.rs +++ b/worker/src/args.rs @@ -1,4 +1,4 @@ -use std::{net::IpAddr, time::Duration}; +use std::time::Duration; use clap::Parser; @@ -6,7 +6,7 @@ use clap::Parser; pub struct WorkerArgs { /// Controller's HTTP address. #[arg(short, long)] - pub ctl_addr: IpAddr, + pub ctl_addr: String, /// Interval at which metrics are pushed to the controller. /// diff --git a/worker/src/main.rs b/worker/src/main.rs index 5b84452..3b63845 100644 --- a/worker/src/main.rs +++ b/worker/src/main.rs @@ -34,7 +34,7 @@ async fn main() -> Result<()> { let args = Arc::new(WorkerArgs::parse()); info!(?args, "started worker"); - let ctl_client = CtlClient::new(args.ctl_addr); + let ctl_client = CtlClient::new(&args.ctl_addr); let proxy_listener = mk_listener(ANY_IP, WORKER_PROXY_PORT).await?; let http_listener = mk_listener(ANY_IP, WORKER_HTTP_PORT).await?;