nodejs服务全局超时回调里取不到process.domain问题

2023-04-13 16:16:02 浏览数 (1)

我们的服务器出现了一个问题,当触发了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

0 人点赞