Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Evaluating Node.js Performance in Event-Driven Microservices Under High-Throughput Workloads

This project aims to evaluate the performance of Node.js in event-driven microservices architecture under high-throughput workloads by replicating a realistic message processing pipeline.

To run and gather consistent performance metrics, almost all the code has been dockerized with specific configurations and locked down versions of dependencies. For example, every Node.js consumer will be resource-limited with 1.5 CPU cores and 1 GB RAM.

The project has been tested on Linux x64 and macOS arm platforms.

Requirements

Hardware requirements

A machine with at least 6 CPU cores and 16 GB of RAM is recommended to run the tests effectively.

Software requirements

Workload types

Three different workload types have been defined:

Type Operations Purpose
I/O PostgreSQL INSERT + file system write per message Tests non-blocking I/O strengths
CPU JSON.parse of a large payload + recursive Fibonacci(25) Tests event loop blocking
Mixed JSON.parse --> validate --> enrich --> SHA-256 --> DB INSERT --> file write Realistic pipeline

Load generator

Each workload type will be tested under two different load patterns generated by the k6 load generator:

  • Baseline: steady load of 500 messages per second.
  • Burst: see sub-section below.

Burst

Time window Target load Phase
0:00 - 3:00 500 msg/s (flat) warm-up/steady state
3:00 - 3:30 500 --> 5,000 (ramp) first spike
3:30 - 5:00 5,000 msg/s (flat) sustained medium load
5:00 - 5:30 5,000 --> 10,000 (ramp) peak spike
5:30 - 7:00 10,000 msg/s (flat) sustained peak load
7:00 - 7:30 10,000 --> 500 (ramp down) recovery begins
7:30 - 10:00 500 msg/s (flat) drain period

Testing scenarios

By mixing each load generator pattern with each workload type, a total of 6 unique scenarios to test are possible. Each single scenario will be executed with 1, 2, and 4 consumer replicas to evaluate the scaling behavior. Additionally, to ensure statistical significance, each scenario will be repeated 5 times. This results in a total of 90 runs (6 scenarios X 3 replica counts X 5 repetitions).

ID Scenario Load Pattern Duration
S1 Baseline I/O Steady 500 msg/s 10 min
S2 Burst I/O 500 --> 5,000 --> 10,000 msg/s 10 min
S3 Baseline CPU Steady 500 msg/s 10 min
S4 Burst CPU 500 --> 5,000 --> 10,000 msg/s 10 min
S5 Baseline Mixed Steady 500 msg/s 10 min
S6 Burst Mixed 500 --> 5,000 --> 10,000 msg/s 10 min

It's important to note that each test will last 10 minutes, it does not matter if the consumers actually finished processing all the messages or not. For each run a dedicated track record will be stored under results/<scenario>/<scenario>-R<replicas>-<repetition> (e.g. results/S2/S2-R4-1 for scenario S2 with 4 replicas on repetition 1).

Services

These are the main services used across the project, all defined in the docker-compose.yml file:

  • Kafka (message broker with KRaft mode)
  • PostgreSQL (I/O target)
  • Prometheus (metrics collection)
  • Grafana (dashboards for live monitoring)
  • cAdvisor (container-level CPU/memory metrics)
  • Consumer (Node.js application being benchmarked)
  • k6 (load generator)
  • Python & Node (analysis and dev utilities)

Architecture

This is a broad overview of the architecture used in the project:

Grafana k6 (xk6-kafka load generator)
    │  produces messages
    ▼
Apache Kafka (KRaft mode, 8-partition topic)
    │  consumes
    ▼
Consumer Group (1, 2, or 4 Node.js replicas)
    │
    │  one of three workload profiles per run:
    ├── I/O   : PostgreSQL INSERT + file write/log
    ├── CPU   : JSON.parse large payload + recursive Fibonacci
    └── Mixed : JSON.parse --> PostgreSQL INSERT --> file write (realistic pipeline)

    Metrics ──► Prometheus ──► Grafana
                     ▲
                     └── cAdvisor (container CPU/memory)

                  Results ──► scripts/analyze.py (statistical summaries)
                          ──► scripts/generate_graphs.py (graphs)

Commands

Run just with no arguments to list every available command grouped by category and refer directly to the justfile for anything not covered below (infrastructure, single scenarios, smoke tests, monitoring, formatting, cleanup...).

These commands showcase how to run the full experiment matrix and analyze the results.

# Build all the Docker images.
just build-all

# Run the full experiment matrix: `6 scenarios X 3 replica counts X 5 repetitions`
# (metrics written to `results/SX/` for each scenario).
just run-all

# Verify all 90 runs produced complete exports.
just audit-data

# Briefly check the results of the 90 runs.
just analyze > results/analyze.txt

# Generate the statistical summaries from the collected results.
just analyze-csv > results/stats.csv
just analyze-json > results/stats.json

# Generate all graphs from the collected results (written to `results/graphs/`).
just generate-graphs

Experiments

In the experiments/ folder are available all the finished executed runs with all the relative metrics, stats generated, graphs and logs. The results/ folder instead is used only for storing the current running test.

About

Evaluating Node.js Performance in Event-Driven Microservices Under High-Throughput Workloads.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages