我们的服务器出现了一个问题,当触发了express的全局超时后,在server.setTimeout的回调里,process.domain是undefined。
由于我们将每次访问产生的reqId、用户id等信息保存在process.domain里。如果取不到process.domain,我们就很难在海量的日志里找出这次的错误日志,给排查线上问题造成了困难。
下面是简化后的代码:
代码语言:javascript复制const domain = require('domain');
const express = require('express');
const app = express();
const http = require('http');
const sleep = (ts) => (new Promise(resolve => setTimeout(resolve, ts)))
app.use((req, res, next) => {
const d = domain.create();
d.id = 999999;
d.add(req);
d.add(res);
d.run(next);
});
let testRouter = express.Router();
testRouter.get('/', async function (req, res) {
await sleep(2000);//等2秒,让程序必定进入全局超时逻辑
res.send('hello world!');
});
app.use('/test', testRouter);
const server = http.createServer(app).listen(3000, '127.0.0.1', () => {});
server.setTimeout(1000, (socket) => {
console.log(process.domain);//这里的结果是undefined
});
在stackoverflow里,看到有个老哥说这是domain作用域的问题,必须要将正确的作用域挂载到domain里。我试了一下,找到了解决方法。
原来我们写的是:
代码语言:javascript复制d.add(req);
d.add(res);
解决方案是将req.socket也加到domain作用域里去,即下面的写法:
代码语言:javascript复制d.add(req);
d.add(res);
d.add(req.socket);
我还没搞懂这个domain作用域到底是咋回事,以后再继续研究一下domain组件的源码:
https://github.com/nodejs/node/blob/master/lib/domain.js