};
});
通过此中间件,可以限制某些功能的响应时长(保证每次处理时间都大于期望值),需要注意的是,延时响应的不要超过全局的超时配置。
接口性能统计
系统是否稳定,性能是否需要优化等都依赖于统计,为了能及时反应出系统状态,并方便添加告警指标,我将相关的统计数据写入influxdb,主要指标如下:
tags:
method,请求类型
type,根据响应状态码分组,1xx -> 1, 2xx -> 2
spdy,根据自定义的响应时间划分区间,方便将接口响应时间分组
route,接口路由
fields:
connecting,处理请求数
use,处理时长
bytes,响应数字长度
code,响应状态码
url,请求地址
ip,用户IP
在influxdb中,tags可用于对数据分组,根据 type 将接口请求分组,将 4 与 5 的单独监控,可以简单快速的把当前接口出错汇总。统计中间件代码如下:
function stats() {
let connecting = 0;
const spdyList = [
100,
300,
1000,
3000,
];
return async (ctx, next) => {
const start = Date.now();
const tags = {
method: ctx.method,
};
connecting++;
const fields = {
connecting,
url: ctx.url,
}
let status = 0;
try {
await next();
} catch (err) {
// 出错时状态码从error中获取
status = err.status;
throw err;
} finally {
// 如果非出错,则从ctx中取状态码
if (!status) {
status = ctx.status;
}
const use = Date.now() - start;
connecting--;
tags.route = ctx._matchedRoute;
tags.type = `${status / 100 | 0}`
let spdy = 0;
// 确认处理时长所在区间
spdyList.forEach((v, i) => {
if (use > v) {
spdy = i + 1;
}
});
tags.spdy = `${spdy}`; fields.use = use;
fields.bytes = ctx.length || 0;
fields.code = status;
fields.ip = ctx.ip;
// 统计数据写入统计系统(如influxdb)
console.info(tags);
console.info(fields);
}
};
}
app.use(stats());
router.post('/users/v1/:type', async (ctx) => {
await new Promise(resolve => setTimeout(resolve, 100))
ctx.body = {
account: 'vicanso',
};
});
接口全日志记录
为了方便排查问题,需要将接口的相关信息输出至日志中,中间件的实现如下:
function tracker() {
const stringify = (data) => JSON.stringify(data, (key, value) => {
// 对于隐私数据做***处理
if (/password/.test(key)) {
return '***';
}









