面试题答案
一键面试日志记录频率控制
- 基于时间间隔:可以设置一个固定的时间间隔,比如每10秒进行一次日志记录。在Express应用中,使用
setInterval
函数来控制这个时间间隔。例如:
const express = require('express');
const app = express();
let logBuffer = [];
setInterval(() => {
if (logBuffer.length > 0) {
// 这里进行实际的日志写入操作,如写入文件或发送到日志服务器
console.log(logBuffer.join('\n'));
logBuffer = [];
}
}, 10000);
app.get('/', (req, res) => {
logBuffer.push(`[${new Date().toISOString()}] GET /`);
res.send('Hello World!');
});
- 基于事件数量:设定在一定数量的请求发生后进行一次日志记录。比如每100个请求记录一次日志。可以通过一个计数器来实现:
const express = require('express');
const app = express();
let logCounter = 0;
let logBuffer = [];
const logThreshold = 100;
app.get('/', (req, res) => {
logBuffer.push(`[${new Date().toISOString()}] GET /`);
logCounter++;
if (logCounter >= logThreshold) {
// 这里进行实际的日志写入操作,如写入文件或发送到日志服务器
console.log(logBuffer.join('\n'));
logBuffer = [];
logCounter = 0;
}
res.send('Hello World!');
});
异步日志写入
- 使用
fs.writeFile
的异步版本:在Node.js中,fs
模块的writeFile
有异步版本fs.writeFile
(回调形式)和fs.promises.writeFile
(Promise形式)。以Promise形式为例:
const express = require('express');
const fs = require('fs').promises;
const app = express();
app.get('/', async (req, res) => {
try {
await fs.writeFile('app.log', `[${new Date().toISOString()}] GET /\n`, { flag: 'a' });
} catch (err) {
console.error('Error writing log:', err);
}
res.send('Hello World!');
});
- 使用队列和工作线程:可以创建一个日志队列,将日志信息放入队列中,然后通过工作线程或Node.js的
worker_threads
模块来异步处理队列中的日志写入操作。这样主线程不会被日志写入操作阻塞。例如:
const { Worker } = require('worker_threads');
const express = require('express');
const app = express();
const logQueue = [];
const worker = new Worker('./log - worker.js');
worker.on('message', (result) => {
if (result === 'done') {
if (logQueue.length > 0) {
const log = logQueue.shift();
worker.postMessage(log);
}
}
});
app.get('/', (req, res) => {
logQueue.push(`[${new Date().toISOString()}] GET /`);
if (logQueue.length === 1) {
worker.postMessage(logQueue[0]);
}
res.send('Hello World!');
});
// log - worker.js
const { parentPort } = require('worker_threads');
const fs = require('fs').promises;
parentPort.on('message', async (log) => {
try {
await fs.writeFile('app.log', log + '\n', { flag: 'a' });
parentPort.postMessage('done');
} catch (err) {
console.error('Error writing log in worker:', err);
parentPort.postMessage('done');
}
});
性能监控数据的高效采集与分析
- 使用
node - native - perf
或node - prof
:这些工具可以帮助采集性能数据,如CPU使用率、内存使用情况等。例如,node - native - perf
可以通过简单的API来采集性能数据:
const nativePerf = require('node - native - perf');
nativePerf.start();
const express = require('express');
const app = express();
app.get('/', (req, res) => {
const perfData = nativePerf.get();
// 可以将perfData发送到监控服务器或进行本地分析
res.send('Hello World!');
});
- 自定义中间件采集请求相关性能数据:在Express应用中,可以创建中间件来记录每个请求的处理时间等性能数据。例如:
const express = require('express');
const app = express();
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const end = Date.now();
const duration = end - start;
// 可以将duration发送到监控服务器或进行本地分析
});
next();
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
- 实时分析与可视化:采集到的数据可以通过WebSocket实时发送到前端,前端使用图表库(如Chart.js)进行实时可视化。或者将数据发送到专业的监控平台(如Prometheus + Grafana)进行分析和展示。例如,使用Socket.io将性能数据实时发送到前端:
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
// 假设这里有采集性能数据的逻辑,比如getPerformanceData()函数
setInterval(() => {
const perfData = getPerformanceData();
io.emit('performance - data', perfData);
}, 5000);
server.listen(3000, () => {
console.log('Server running on port 3000');
});
在前端HTML页面中:
<!DOCTYPE html>
<html>
<head>
<title>Performance Monitor</title>
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="performanceChart"></canvas>
<script>
const socket = io();
const ctx = document.getElementById('performanceChart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Performance Metrics',
data: [],
borderColor: 'blue',
fill: false
}]
},
options: {
scales: {
x: {
type: 'time'
}
}
}
});
socket.on('performance - data', (data) => {
chart.data.labels.push(new Date());
chart.data.datasets[0].data.push(data.value);
chart.update();
});
</script>
</body>
</html>