mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-19 14:59:43 +08:00
perf: reduce resident dependencies and duplicate WebSocket authentication (#3071)
* perf: load HTTP dependencies only in the HTTP worker * docs: record 30-minute idle resource comparison * perf: isolate database initialization from the cluster primary * docs: record isolated database startup resource comparison * perf: avoid an extra shell child in Docker health probes * perf: load notification dependencies only when needed * perf: retain queue cleanup after notification loading comparison * fix: stop page polling after unmount and avoid duplicate fetches * perf: share WebSocket session polling across connections * docs: measure real WebSocket container CPU and memory * perf: reuse JWT validation within each WebSocket session check * perf: bound login IP lookup allocations with an address cache * refactor: limit resource optimization PR to three core changes * docs: benchmark the three core optimizations against develop * chore: remove documentation and benchmark artifacts from PR
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const { createRequire } = require('node:module');
|
||||
const path = require('node:path');
|
||||
const ts = require('typescript');
|
||||
const source = fs.readFileSync('back/app.ts', 'utf8');
|
||||
const compiled = ts.transpileModule(
|
||||
source.slice(0, source.indexOf('\nconst app = new Application();')) +
|
||||
'\nmodule.exports = Application;',
|
||||
{
|
||||
compilerOptions: {
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
target: ts.ScriptTarget.ES2020,
|
||||
esModuleInterop: true,
|
||||
},
|
||||
},
|
||||
).outputText;
|
||||
|
||||
function fixture() {
|
||||
const required = [],
|
||||
listeners = new Map();
|
||||
let invalidations = 0;
|
||||
const module = { exports: {} };
|
||||
const localRequire = createRequire(path.resolve('back/app.ts'));
|
||||
const mocks = {
|
||||
'./config': { cors: { origin: ['http://localhost'] } },
|
||||
'./loaders/logger': { error() {}, warn() {}, info() {} },
|
||||
'./middlewares/monitoring': {
|
||||
monitoringMiddleware: (_req, _res, next) => next(),
|
||||
},
|
||||
'./schedule/client': {
|
||||
default: { readiness: { invalidate: () => invalidations++ } },
|
||||
__esModule: true,
|
||||
},
|
||||
};
|
||||
new Function('require', 'module', 'exports', 'process', compiled)(
|
||||
(name) => {
|
||||
required.push(name);
|
||||
return Object.hasOwn(mocks, name) ? mocks[name] : localRequire(name);
|
||||
},
|
||||
module,
|
||||
module.exports,
|
||||
{ env: {}, on: (name, fn) => listeners.set(name, fn) },
|
||||
);
|
||||
return {
|
||||
app: new module.exports(),
|
||||
required,
|
||||
listeners,
|
||||
invalidations: () => invalidations,
|
||||
};
|
||||
}
|
||||
|
||||
test('primary construction does not load HTTP middleware, metrics or the gRPC client', () => {
|
||||
const { required } = fixture();
|
||||
for (const name of [
|
||||
'express',
|
||||
'helmet',
|
||||
'cors',
|
||||
'compression',
|
||||
'./middlewares/monitoring',
|
||||
'./schedule/client',
|
||||
'./config/util',
|
||||
]) {
|
||||
assert.equal(required.includes(name), false, name);
|
||||
}
|
||||
});
|
||||
|
||||
test('lazy HTTP initialization preserves query filtering, security headers, CORS and compression', async (t) => {
|
||||
const { app, required } = fixture();
|
||||
const http = await app.setupMiddlewares();
|
||||
http.get('/test', (req, res) =>
|
||||
res.json({ query: req.query, data: 'x'.repeat(2048) }),
|
||||
);
|
||||
const server = await new Promise((resolve) => {
|
||||
const server = http.listen(0, '127.0.0.1', () => resolve(server));
|
||||
});
|
||||
t.after(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
server.close(resolve);
|
||||
server.closeAllConnections();
|
||||
}),
|
||||
);
|
||||
const response = await fetch(
|
||||
`http://127.0.0.1:${server.address().port}/test?t=123&keep=yes`,
|
||||
{
|
||||
headers: { Origin: 'http://localhost', 'Accept-Encoding': 'gzip' },
|
||||
},
|
||||
);
|
||||
assert.equal(response.status, 200);
|
||||
assert.equal(response.headers.get('x-content-type-options'), 'nosniff');
|
||||
assert.equal(
|
||||
response.headers.get('access-control-allow-origin'),
|
||||
'http://localhost',
|
||||
);
|
||||
assert.equal(response.headers.get('content-encoding'), 'gzip');
|
||||
assert.deepEqual((await response.json()).query, { keep: 'yes' });
|
||||
assert.ok(required.includes('express'));
|
||||
assert.equal(required.includes('./schedule/client'), false);
|
||||
});
|
||||
|
||||
test('worker recovery messages still invalidate HTTP readiness, but gRPC shutdown setup does not load its client', async () => {
|
||||
const grpc = fixture();
|
||||
grpc.app.setupWorkerShutdown('grpc');
|
||||
await grpc.listeners.get('message')('scheduler-unavailable');
|
||||
assert.equal(grpc.required.includes('./schedule/client'), false);
|
||||
const http = fixture();
|
||||
http.app.setupWorkerShutdown('http');
|
||||
await http.listeners.get('message')('scheduler-unavailable');
|
||||
await http.listeners.get('message')('reregister-crons');
|
||||
assert.equal(http.invalidations(), 2);
|
||||
const shutdowns = [];
|
||||
http.app.gracefulShutdown = (role) => shutdowns.push(role);
|
||||
await http.listeners.get('message')('shutdown');
|
||||
http.listeners.get('SIGTERM')();
|
||||
assert.deepEqual(shutdowns, ['http', 'http']);
|
||||
});
|
||||
Reference in New Issue
Block a user