This commit is contained in:
Wyle.Gong-巩文昕
2025-04-23 11:21:08 +08:00
parent fc643727f3
commit 7a1aae1e2f
135 changed files with 221483 additions and 1 deletions
+59
View File
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
crossorigin="anonymous">
</head>
<body>
<script type="module" src="./bench.js"></script>
<div class="container">
<h1 id="title">WS NATS Browser Performance</h1>
<label for="server">NATS Websocket Server</label>
<input type="text" class="form-control" id="server" placeholder="server" autocomplete="off"
value="localhost:9222"><br/>
<label for="ws">Use ws:// (uncheck for wss://)</label>
<input type="checkbox" class="form-check-input" id="ws" value="true" checked><br/>
<label for="subject">Subject</label>
<input type="text" class="form-control" id="subject" placeholder="subject" autocomplete="off" value="foo"><br/>
<label for="count">Count</label>
<input type="number" class="form-control" id="count" placeholder="messages" autocomplete="off"
value="100000"><br/>
<label for="payload">Payload size</label>
<input type="number" class="form-control" id="payload" placeholder="payload size in bytes" autocomplete="off"
value="0"><br/>
<label for="callbacks">Use callbacks</label>
<input type="checkbox" class="form-check-input" id="callbacks" value="true" checked><br/>
<h3>Test</h3>
<div class="radio-inline">
<label><input class="form-check-input" type="radio" value="pubsub" checked id="pubsub"
name="test">Pub/Sub</label>
</div>
<div class="radio-inline">
<label><input class="form-check-input" type="radio" value="pub" id="pub" name="test">Publish</label>
</div>
<div class="radio-inline">
<label><input class="form-check-input" type="radio" value="sub" id="sub" name="test">Subscribe</label>
</div>
<div class="radio-inline">
<label><input class="form-check-input" type="radio" value="sub" id="reqrep" name="test">ReqReq</label>
</div>
<br/><br/>
<button id="send" onclick="benchapp.run()" class="btn btn-primary">Start</button>
</div>
<br/>
<div class="container">
<pre id="results"></pre>
</div>
</body>
</html>
+151
View File
@@ -0,0 +1,151 @@
/*
* Copyright 2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Bench, connect, Metric } from "../esm/nats.js";
function getString(id) {
return document.getElementById(id).value;
}
function isChecked(id) {
return document.getElementById(id).checked;
}
function getTestChoice() {
if (isChecked("pubsub")) {
return "pubsub";
} else if (isChecked("pub")) {
return "pub";
} else if (isChecked("sub")) {
return "sub";
} else if (isChecked("reqrep")) {
return "reqrep";
}
}
function getNumber(id) {
const v = getString(id);
if (!isNaN(v)) {
return parseInt(v, 10);
}
return -1;
}
function updateResults(s) {
const p = document.createElement("pre");
p.appendChild(document.createTextNode(s));
document.getElementById("results").appendChild(p);
}
async function run() {
const server = getString("server");
const ws = isChecked("ws");
const nc = await connect(
{
servers: `${ws ? "ws://" : "wss://"}${server}`,
pendingLimit: 8192,
},
);
nc.closed()
.then((err) => {
if (err) {
console.error(err);
}
});
const kind = getTestChoice();
const t = {};
t.callbacks = isChecked("callbacks");
t.msgs = getNumber("count");
t.size = getNumber("payload");
t.subject = getString("subject");
t.pub = kind === "pub" || kind === "pubsub";
t.sub = kind === "sub" || kind === "pubsub";
t.req = kind === "reqrep";
t.rep = kind === "reqrep";
const bench = new Bench(nc, t);
const m = await bench.run();
const metrics = [];
metrics.push(...m);
await nc.close();
const pubsub = metrics.filter((m) => m.name === "pubsub").reduce(
reducer,
new Metric("pubsub", 0),
);
const reqrep = metrics.filter((m) => m.name === "reqrep").reduce(
reducer,
new Metric("reqrep", 0),
);
const pub = metrics.filter((m) => m.name === "pub").reduce(
reducer,
new Metric("pub", 0),
);
const sub = metrics.filter((m) => m.name === "sub").reduce(
reducer,
new Metric("sub", 0),
);
const req = metrics.filter((m) => m.name === "req").reduce(
reducer,
new Metric("req", 0),
);
const rep = metrics.filter((m) => m.name === "rep").reduce(
reducer,
new Metric("rep", 0),
);
const report = [];
if (pubsub && pubsub.msgs) {
report.push(pubsub.toString());
}
if (reqrep && reqrep.msgs) {
report.push(reqrep.toString());
}
if (pub && pub.msgs) {
report.push(pub.toString());
}
if (sub && sub.msgs) {
report.push(sub.toString());
}
if (req && req.msgs) {
report.push(req.toString());
}
if (rep && rep.msgs) {
report.push(rep.toString());
}
updateResults(report.join("\n"));
}
const reducer = (a, m) => {
if (a) {
a.name = m.name;
a.payload = m.payload;
a.bytes += m.bytes;
a.duration += m.duration;
a.msgs += m.msgs;
a.lang = m.lang;
a.version = m.version;
a.async = m.async;
a.max = Math.max(a.max === undefined ? 0 : a.max, m.duration);
a.min = Math.min(a.min === undefined ? m.duration : a.max, m.duration);
}
return a;
};
window.benchapp = {
run: run,
};
+30
View File
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ws-nats chat</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
crossorigin="anonymous">
<script type="module" src="/assets/nats.ws-1.30.3/examples/chat.js"></script>
</head>
<!-- when the browser exits, we publish a message -->
<body onunload="chat.exiting()">
<!-- a form for entering messages -->
<div class="container">
<h1>ws-nats chat</h1>
<input type="text" class="form-control" id="data" placeholder="Message" autocomplete="off"><br />
<button id="send" onclick="chat.send()" class="btn btn-primary">Send</button>
</div>
<br />
<!-- a place to record messages -->
<div id="chats" class="container"></div>
</body>
</html>
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright 2020 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { connect, JSONCodec } from "/assets/nats.ws-1.30.3/esm/nats.js";
const me = Date.now();
window.chat = {
send: send,
exiting: exiting,
};
// create a decoder, the client is sending JSON
const jc = JSONCodec();
// create a connection, and register listeners
const init = async function () {
// if the connection doesn't resolve, an exception is thrown
// a real app would allow configuring the hostport and whether
// to use WSS or not.
const conn = await connect(
{ servers: "ws://localhost:9222" },
);
// handle connection to the server is closed - should disable the ui
conn.closed().then((err) => {
let m = "NATS connection closed";
addEntry(`${m} ${err ? err.message : ""}`);
});
(async () => {
for await (const s of conn.status()) {
addEntry(`Received status update: ${s.type}`);
}
})().then();
// the chat application listens for messages sent under the subject 'chat'
(async () => {
const chat = conn.subscribe("chat");
for await (const m of chat) {
const jm = jc.decode(m.data);
addEntry(
jm.id === me ? `(me): ${jm.m}` : `(${jm.id}): ${jm.m}`,
);
}
})().then();
// when a new browser joins, the joining browser publishes an 'enter' message
(async () => {
const enter = conn.subscribe("enter");
for await (const m of enter) {
const jm = jc.decode(m.data);
addEntry(`${jm.id} entered.`);
}
})().then();
(async () => {
const exit = conn.subscribe("exit");
for await (const m of exit) {
const jm = jc.decode(m.data);
if (jm.id !== me) {
addEntry(`${jm.id} exited.`);
}
}
})().then();
// we connected, and we publish our enter message
conn.publish("enter", jc.encode({ id: me }));
return conn;
};
init().then((conn) => {
window.nc = conn;
}).catch((ex) => {
addEntry(`Error connecting to NATS: ${ex}`);
});
// this is the input field
let input = document.getElementById("data");
// add a listener to detect edits. If they hit Enter, we publish it
input.addEventListener("keyup", (e) => {
if (e.key === "Enter") {
document.getElementById("send").click();
} else {
e.preventDefault();
}
});
// send a message if user typed one
function send() {
input = document.getElementById("data");
const m = input.value;
if (m !== "" && window.nc) {
window.nc.publish("chat", jc.encode({ id: me, m: m }));
input.value = "";
}
return false;
}
// send the exit message
function exiting() {
if (window.nc) {
window.nc.publish("exit", jc.encode({ id: me }));
}
}
// add an entry to the document
function addEntry(s) {
const p = document.createElement("pre");
p.appendChild(document.createTextNode(s));
document.getElementById("chats").appendChild(p);
}
+79
View File
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
crossorigin="anonymous">
</head>
<body>
<!-- a place to record messages -->
<div id="messages" class="container"></div>
<!-- load a script -->
<script type="module">
import { connect, StringCodec, credsAuthenticator } from '../esm/nats.js'
// add an entry to the document
function addEntry (s) {
const p = document.createElement('pre')
p.appendChild(document.createTextNode(s))
document.getElementById('messages').appendChild(p)
}
const sc = StringCodec()
async function testConnection (nc) {
addEntry('connected to NATS!')
// simple publisher
nc.publish('hello', sc.encode('nats'))
addEntry('published a message to `hello`')
// simple subscriber, if the message has a reply subject
// send a reply
const sub = await nc.subscribe('help');
(async () => {
addEntry('listening for request on `help`')
for await (const m of sub) {
m.respond(sc.encode(`I can help ${sc.decode(m.data)}`))
}
})().then()
// request data - requests only receive one message
// to receive multiple messages, create a subscription
addEntry('making a request to `help`')
const msg = await nc.request('help', sc.encode('nats request'))
addEntry(`got response '${sc.decode(msg.data)}'`)
// close the connection
nc.close()
addEntry('closed the connection')
}
async function init () {
// To connect to NGS you need a creds or jwt authenticator
// you can create one with nsc:
// nsc add operator -u synadia
// nsc add account myaccount
// nsc add user myuser
// nsc generate creds -a myaccount -n myuser -o ./myuser.creds
// fetch the creds
const creds = await fetch('./myuser.creds')
if (!creds.ok) {
addEntry("unable to find ./myuser.creds - aborting")
return;
}
const token = await creds.text()
const auth = credsAuthenticator(sc.encode(token))
// connect
let nc = await connect({ servers: 'wss://connect.ngs.global', authenticator: auth, debug: true })
await testConnection(nc)
await nc.closed
}
init()
</script>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
port: 4222
websocket: {
port: 9222
no_tls: true
compression: true
}
+20
View File
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
crossorigin="anonymous">
<script type="module" src="/assets/nats.ws-1.30.3/examples/simple.js"></script>
</head>
<body>
<!-- a place to record messages -->
<div id="messages" class="container"></div>
<!-- load a script -->
</body>
</html>
+8
View File
@@ -0,0 +1,8 @@
port: 4222
websocket: {
port: 443
tls: {
cert_file: "../certs/cert.pem"
key_file: "../certs/key.pem"
}
}
+42
View File
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
crossorigin="anonymous">
</head>
<body>
<!-- a place to record messages -->
<div id="messages" class="container"></div>
<!-- load a script -->
<script type="module">
import { connect } from '../nats.js'
// add an entry to the document
function addEntry(s) {
const p = document.createElement("pre");
p.appendChild(document.createTextNode(s));
document.getElementById("messages").appendChild(p);
}
const init = async function () {
try {
// create a connection to a wss server
const nc = await connect({ servers: 'wss://localhost:9222' });
addEntry('connected!');
await nc.flush();
addEntry('did a round-trip to the server');
// close the connection
await nc.close();
addEntry('closed the connection');
} catch(err) {
addEntry(`error connecting - did you setup a wss server? ${err}`);
console.error(err)
}
}
init();
</script>
</body>
</html>