Koa 使用小技巧(小结)

2020-06-17 06:12:42易采站长站整理

status = err.status
} else {
// 非主动抛出异常,则触发error事件,记录异常日志
ctx.app.emit("error", err, ctx);
}
ctx.status = status;
ctx.body = {
message,
};
}
})

app.use((ctx) => {
// 代码异常
// ctx.i.j = 0;
// 主动抛出异常
ctx.throw(400, '参数错误');
});

通过此调整后,将逻辑主动抛出异常与程序异常区分开,定时去查看异常日志,减少程序异常。此例子只是简单的使用了http-errors来创建主动抛出的异常,在实际使用中,可以根据自己的场景创建自定义的Error类,定制相应的异常信息。

当前正在处理请求数

得益于nodejs的IO处理,koa在高并发的场景下的CPU、内存都占用并不高,但是也因为这样,如果只通过CPU、内存来监控程序运行状态并不全面,因此需要增加当前处理请求数的监控,代码如下:


let processingCount = 0;
const maxProcessingCount = 1000;
app.use(async (ctx, next) => {
processingCount++;
if (processingCount > maxProcessingCount) {
// 如果需要也可以直接在处理请求超时时,直接出错
console.error("processing request over limit");
}
try {
await next();
} catch (err) {
throw err;
} finally {
processingCount--;
}
});

app.use(async (ctx) => {
// 延时一秒
await new Promise(resolve => setTimeout(resolve, 1000));
ctx.body = {
account: 'vicanso',
};
});

此中间件在接收到请求时,将处理请求数加一,在处理完成后减一。最大的处理请求数根据系统的性能与用户数量选择合理的值。如果接口处理慢或者突然并发请求暴涨的时,可以尽早得知异常情况,尽早排查。

延时响应

接口的处理一般而言都是希望越快越好,但有些场景我们不希望接口响应的太快(如注册),避免恶意者迅速尝试功能,因此需要一个延时响应的中间件,代码如下:


function delayResponse(delayMs) {
const delay = (t) => {
const d = delayMs - (Date.now() - t);
// 如果处理时长已超过delayMs,无需等待
if (d <= 0) {
return Promise.resolve();
}
return new Promise(resolve => setTimeout(resolve, d));
}
return async(ctx, next) => {
const startedAt = Date.now();
try {
await next();
// 成功处理时等待
await delay(startedAt);
} catch (err) {
// 失败时也等待
await delay(startedAt);
throw err;
}
}
}

router.post('/users/v1/register', delayResponse(1000), (ctx) => {
ctx.body = {
account: 'vicanso',