Add a NATS cluster message-speed bench (throughput and delay).
Some checks are pending
offline / test (push) Waiting to run
Some checks are pending
offline / test (push) Waiting to run
Client LXC 510 against nats-a/b/c at several core and JetStream r=3 loads.
This commit is contained in:
parent
8f0ea8dd31
commit
fef7590c27
34 changed files with 708 additions and 1 deletions
105
packages/verae-nats-cluster/scripts/latency.mjs
Normal file
105
packages/verae-nats-cluster/scripts/latency.mjs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Pub→sub round trip through the cluster (two connections).
|
||||
* Usage: NATS_URL=... node latency.mjs [count] [payloadBytes] [publishers] [ping|flood]
|
||||
* ping = sequential publish-wait (one-message RTT)
|
||||
* flood = publish the batch then drain (queueing under burst)
|
||||
*/
|
||||
import { connect, headers } from "nats";
|
||||
|
||||
const url = process.env.NATS_URL || "nats://10.10.10.21:4222";
|
||||
const count = Number(process.argv[2] || 5000);
|
||||
const size = Number(process.argv[3] || 128);
|
||||
const pubs = Number(process.argv[4] || 1);
|
||||
const mode = process.argv[5] || "flood";
|
||||
const servers = url.split(",").map((s) => s.trim());
|
||||
const subject = `bench.lat.${process.pid}`;
|
||||
const payload = new Uint8Array(size);
|
||||
|
||||
function pct(sorted, p) {
|
||||
if (!sorted.length) return 0;
|
||||
const i = Math.min(sorted.length - 1, Math.floor((p / 100) * sorted.length));
|
||||
return sorted[i];
|
||||
}
|
||||
|
||||
const samples = [];
|
||||
if (mode === "ping") {
|
||||
const subNc = await connect({ servers, name: "lat-sub" });
|
||||
const pubNc = await connect({ servers, name: "lat-pub" });
|
||||
let resolveOne = null;
|
||||
const sub = subNc.subscribe(subject, { max: count });
|
||||
const consume = (async () => {
|
||||
for await (const m of sub) {
|
||||
const sent = Number(m.headers?.get("t") || 0);
|
||||
samples.push(Number(process.hrtime.bigint() / 1000n) - sent);
|
||||
resolveOne?.();
|
||||
}
|
||||
})();
|
||||
await subNc.flush();
|
||||
for (let i = 0; i < count; i++) {
|
||||
const got = new Promise((r) => {
|
||||
resolveOne = r;
|
||||
});
|
||||
const h = headers();
|
||||
h.set("t", String(process.hrtime.bigint() / 1000n));
|
||||
pubNc.publish(subject, payload, { headers: h });
|
||||
await got;
|
||||
}
|
||||
await consume;
|
||||
await pubNc.close();
|
||||
await subNc.close();
|
||||
} else {
|
||||
const subNc = await connect({ servers, name: "lat-sub" });
|
||||
const sub = subNc.subscribe(subject, { max: count });
|
||||
const done = (async () => {
|
||||
for await (const m of sub) {
|
||||
const sent = Number(m.headers?.get("t") || 0);
|
||||
if (sent) samples.push(Number(process.hrtime.bigint() / 1000n) - sent);
|
||||
}
|
||||
})();
|
||||
await subNc.flush();
|
||||
const per = Math.ceil(count / pubs);
|
||||
const publishers = [];
|
||||
for (let p = 0; p < pubs; p++) {
|
||||
publishers.push(
|
||||
(async () => {
|
||||
const nc = await connect({ servers, name: `lat-pub-${p}` });
|
||||
const n = p === pubs - 1 ? count - per * (pubs - 1) : per;
|
||||
for (let i = 0; i < n; i++) {
|
||||
const h = headers();
|
||||
h.set("t", String(process.hrtime.bigint() / 1000n));
|
||||
nc.publish(subject, payload, { headers: h });
|
||||
}
|
||||
await nc.flush();
|
||||
await nc.close();
|
||||
})(),
|
||||
);
|
||||
}
|
||||
await Promise.all(publishers);
|
||||
await done;
|
||||
await subNc.close();
|
||||
}
|
||||
|
||||
samples.sort((a, b) => a - b);
|
||||
const sum = samples.reduce((a, b) => a + b, 0);
|
||||
const us = (n) => `${(n / 1000).toFixed(3)}ms`;
|
||||
console.log(
|
||||
JSON.stringify({
|
||||
count: samples.length,
|
||||
pubs,
|
||||
size,
|
||||
mode,
|
||||
min_us: samples[0],
|
||||
avg_us: Math.round(sum / samples.length),
|
||||
p50_us: pct(samples, 50),
|
||||
p90_us: pct(samples, 90),
|
||||
p99_us: pct(samples, 99),
|
||||
max_us: samples[samples.length - 1],
|
||||
min: us(samples[0]),
|
||||
avg: us(sum / samples.length),
|
||||
p50: us(pct(samples, 50)),
|
||||
p90: us(pct(samples, 90)),
|
||||
p99: us(pct(samples, 99)),
|
||||
max: us(samples[samples.length - 1]),
|
||||
}),
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue