174 lines
5.7 KiB
Markdown
174 lines
5.7 KiB
Markdown
# k6 Load Tests for Cart API
|
||
|
||
This directory contains a k6 script (`cart_load_test.js`) to stress and observe the cart actor HTTP API.
|
||
|
||
## Contents
|
||
|
||
- `cart_load_test.js` – primary k6 scenario script
|
||
- `README.md` – this file
|
||
|
||
## Prerequisites
|
||
|
||
- Node not required (k6 runs standalone)
|
||
- k6 installed (>= v0.43 recommended)
|
||
- Prometheus + Grafana (optional) if you want to correlate with the dashboard you generated
|
||
- A running cart service exposing HTTP endpoints at (default) `http://localhost:8080/cart`
|
||
|
||
## Endpoints Exercised
|
||
|
||
The script exercises (per iteration):
|
||
|
||
1. `GET /cart/` – ensure / fetch cart state (creates cart if missing; sets `cartid` & `cartowner` cookies)
|
||
2. `POST /cart/` – add item mutation (random SKU & quantity)
|
||
3. `GET /cart/` – fetch after mutations
|
||
4. `GET /cart/checkout` – occasionally (~2% of iterations) to simulate checkout start
|
||
|
||
You can extend it easily to hit deliveries, quantity changes, or removal endpoints.
|
||
|
||
## Environment Variables
|
||
|
||
| Variable | Purpose | Default |
|
||
|-----------------|----------------------------------------------|-------------------------|
|
||
| `BASE_URL` | Base URL root (either host or host/cart) | `http://localhost:8080/cart` |
|
||
| `VUS` | VUs for steady_mutations scenario | `20` |
|
||
| `DURATION` | Duration for steady_mutations scenario | `5m` |
|
||
| `RAMP_TARGET` | Peak VUs for ramp_up scenario | `50` |
|
||
|
||
You can also disable one scenario by editing `options.scenarios` inside the script.
|
||
|
||
Example run:
|
||
|
||
```bash
|
||
k6 run \
|
||
-e BASE_URL=https://cart.prod.example.com/cart \
|
||
-e VUS=40 \
|
||
-e DURATION=10m \
|
||
-e RAMP_TARGET=120 \
|
||
k6/cart_load_test.js
|
||
```
|
||
|
||
## Metrics (Custom)
|
||
|
||
The script defines additional k6 metrics:
|
||
|
||
- `cart_add_item_duration` (Trend) – latency of POST add item
|
||
- `cart_fetch_duration` (Trend) – latency of GET cart state
|
||
- `cart_checkout_duration` (Trend) – latency of checkout
|
||
- `cart_items_added` (Counter) – successful add item operations
|
||
- `cart_checkout_calls` (Counter) – successful checkout calls
|
||
|
||
Thresholds (in `options.thresholds`) enforce basic SLO:
|
||
- Mutation failure rate < 2%
|
||
- p90 mutation latency < 800 ms
|
||
- p99 overall HTTP latency < 1500 ms
|
||
|
||
Adjust thresholds to your environment if they trigger prematurely.
|
||
|
||
## Cookies & Stickiness
|
||
|
||
The script preserves:
|
||
- `cartid` – cart identity (server sets expiry separately)
|
||
- `cartowner` – owning host for sticky routing
|
||
|
||
If your load balancer or ingress enforces affinity based on these cookies, traffic will naturally concentrate on the originally claimed host for each cart under test.
|
||
|
||
## SKU Set
|
||
|
||
SKUs used (randomly selected each mutation):
|
||
|
||
```
|
||
778290 778345 778317 778277 778267 778376 778244 778384
|
||
778365 778377 778255 778286 778246 778270 778266 778285
|
||
778329 778425 778407 778418 778430 778469 778358 778351
|
||
778319 778307 778278 778251 778253 778261 778263 778273
|
||
778281 778294 778297 778302
|
||
```
|
||
|
||
To add/remove SKUs, edit the `SKUS` array. Keeping it non-empty and moderately sized helps randomization.
|
||
|
||
## Extending the Script
|
||
|
||
### Add Quantity Change
|
||
|
||
```js
|
||
function changeQuantity(itemId, newQty) {
|
||
const payload = JSON.stringify({ Id: itemId, Qty: newQty });
|
||
http.put(baseUrl() + '/', payload, { headers: headers() });
|
||
}
|
||
```
|
||
|
||
### Remove Item
|
||
|
||
```js
|
||
function removeItem(itemId) {
|
||
http.del(baseUrl() + '/' + itemId, null, { headers: headers() });
|
||
}
|
||
```
|
||
|
||
### Add Delivery
|
||
|
||
```js
|
||
function addDelivery(itemIds) {
|
||
const payload = JSON.stringify({ provider: "POSTNORD", items: itemIds });
|
||
http.post(baseUrl() + '/delivery', payload, { headers: headers() });
|
||
}
|
||
```
|
||
|
||
You can integrate these into the iteration loop with probabilities.
|
||
|
||
## Output Summary
|
||
|
||
`handleSummary` outputs a JSON summary to stdout:
|
||
- Average & p95 mutation latencies (if present)
|
||
- Fetch p95
|
||
- Checkout count
|
||
- Check statuses
|
||
|
||
Redirect or parse that output for CI pipelines.
|
||
|
||
## Running in CI
|
||
|
||
Use shorter durations (e.g. `DURATION=2m VUS=10`) to keep builds fast. Fail build on threshold breaches:
|
||
|
||
```bash
|
||
k6 run -e BASE_URL=$TARGET -e VUS=10 -e DURATION=2m k6/cart_load_test.js || exit 1
|
||
```
|
||
|
||
## Correlating with Prometheus / Grafana
|
||
|
||
During load, observe:
|
||
- `cart_mutations_total` growth and latency histograms
|
||
- Event log write rate (`cart_event_log_appends_total`)
|
||
- Pool usage (`cart_grain_pool_usage`) and spawn rate (`cart_grain_spawned_total`)
|
||
- Failure counters (`cart_mutation_failures_total`) ensure they remain low
|
||
|
||
If mutation latency spikes without high error rate, inspect external dependencies (e.g., product fetcher or Klarna endpoints).
|
||
|
||
## Common Tuning Tips
|
||
|
||
| Symptom | Potential Adjustment |
|
||
|------------------------------------|---------------------------------------------------|
|
||
| High latency p99 | Increase CPU/memory, optimize mutation handlers |
|
||
| Pool at capacity | Raise pool size argument or TTL |
|
||
| Frequent cart eviction mid-test | Confirm TTL is sliding (now 2h on mutation) |
|
||
| High replay duration | Consider snapshot + truncate event logs |
|
||
| Uneven host load | Verify `cartowner` cookie is respected upstream |
|
||
|
||
## Safety / Load Guardrails
|
||
|
||
- Start with low VUs (5–10) and short duration.
|
||
- Scale incrementally to find saturation points.
|
||
- If using production endpoints, coordinate off-peak runs.
|
||
|
||
## License / Attribution
|
||
|
||
This test script is tailored for your internal cart actor system; adapt freely. k6 is open-source (AGPL v3). Ensure compliance if redistributing.
|
||
|
||
---
|
||
|
||
Feel free to request:
|
||
- A variant script for spike tests
|
||
- WebSocket / long poll integration (if added later)
|
||
- Synthetic error injection harness
|
||
|
||
Happy load testing! |