全站请求耗时统计工具设计方案

设计一套全站请求耗时统计工具需要从数据采集、数据传输、数据存储和数据分析展示等多个方面进行考虑。以下是一个详细的设计方案:
1. 数据采集
1.1 前端数据采集
- XMLHttpRequest 和 Fetch API 拦截:通过重写
XMLHttpRequest
和fetch
方法,拦截所有请求,记录请求的开始时间、结束时间、请求URL、请求方法、响应状态码等信息。 - Performance API:使用
Performance API
获取页面加载性能数据,包括资源加载时间、DNS查询时间、TCP连接时间等。 - 自定义事件:在关键业务逻辑中添加自定义事件,记录用户操作的耗时。
1.2 后端数据采集
- 中间件拦截:在服务器端使用中间件拦截所有请求,记录请求的开始时间、结束时间、请求URL、请求方法、响应状态码等信息。
- 日志记录:将请求耗时数据记录到日志文件中,便于后续分析。
2. 数据传输
- 前端数据传输:前端采集到的数据可以通过
Beacon API
或XMLHttpRequest
发送到后端服务器。Beacon API
适合在页面卸载时发送数据,确保数据不会丢失。 - 后端数据传输:后端采集到的数据可以通过日志收集系统(如 Fluentd、Logstash)传输到中央存储系统。
3. 数据存储
- 时序数据库:使用时序数据库(如 InfluxDB、Prometheus)存储请求耗时数据,时序数据库适合存储时间序列数据,便于后续的时间范围查询和聚合分析。
- 分布式存储:如果数据量较大,可以考虑使用分布式存储系统(如 Hadoop HDFS、Cassandra)存储原始日志数据。
4. 数据分析与展示
4.1 数据处理
- 数据清洗:对采集到的数据进行清洗,去除无效数据、重复数据等。
- 数据聚合:对数据进行聚合分析,计算平均耗时、最大耗时、最小耗时、95分位耗时等指标。
4.2 数据展示
- 仪表盘:使用可视化工具(如 Grafana、Kibana)创建仪表盘,展示请求耗时的趋势图、分布图、Top N 慢请求等。
- 报警系统:设置报警规则,当请求耗时超过设定的阈值时,触发报警通知相关人员。
5. 工具链集成
- 构建工具集成:将数据采集代码集成到前端构建工具(如 Webpack、Vite)中,确保在构建时自动注入采集代码。
- CI/CD 集成:将数据采集和分析工具集成到 CI/CD 流水线中,确保每次发布后自动进行性能监控和分析。
6. 安全性考虑
- 数据脱敏:对敏感数据进行脱敏处理,确保用户隐私数据不被泄露。
- 访问控制:对数据存储和展示系统进行访问控制,确保只有授权人员可以访问和操作数据。
7. 性能优化
- 数据采样:在高并发场景下,可以采用数据采样策略,只采集部分请求的耗时数据,减少数据传输和存储的压力。
- 异步处理:数据采集和传输过程尽量采用异步处理,避免阻塞主线程,影响用户体验。
8. 扩展性考虑
- 插件化设计:将数据采集、传输、存储、分析等模块设计为插件化,便于后续扩展和替换。
- 多语言支持:如果系统涉及多语言开发,确保数据采集工具支持多语言环境。
9. 示例代码
前端数据采集示例
// 重写 fetch 方法
const originalFetch = window.fetch;
window.fetch = function(...args) {
const startTime = performance.now();
return originalFetch.apply(this, args).then(response => {
const endTime = performance.now();
const duration = endTime - startTime;
const url = args[0];
const method = args[1] ? args[1].method || 'GET' : 'GET';
const status = response.status;
// 发送数据到后端
navigator.sendBeacon('/log', JSON.stringify({
url,
method,
status,
duration,
timestamp: new Date().toISOString()
}));
return response;
});
};
// 重写 XMLHttpRequest 方法
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
this._startTime = performance.now();
this._method = method;
this._url = url;
return originalOpen.apply(this, arguments);
};
const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
const startTime = this._startTime;
this.addEventListener('load', function() {
const endTime = performance.now();
const duration = endTime - startTime;
const status = this.status;
// 发送数据到后端
navigator.sendBeacon('/log', JSON.stringify({
url: this._url,
method: this._method,
status,
duration,
timestamp: new Date().toISOString()
}));
});
return originalSend.apply(this, arguments);
};
后端数据采集示例(Node.js + Express)
const express = require('express');
const app = express();
app.use((req, res, next) => {
const startTime = Date.now();
res.on('finish', () => {
const endTime = Date.now();
const duration = endTime - startTime;
const url = req.originalUrl;
const method = req.method;
const status = res.statusCode;
// 记录日志
console.log(JSON.stringify({
url,
method,
status,
duration,
timestamp: new Date().toISOString()
}));
});
next();
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
总结
这套全站请求耗时统计工具涵盖了从前端到后端的数据采集、传输、存储和分析展示的全流程,能够帮助开发团队全面监控和分析系统的性能瓶颈,优化用户体验。通过合理的架构设计和工具链集成,可以确保系统的可扩展性、安全性和性能。