3

这是我的节点 js 后端 API 方法。

apiRouter.route('/makeComment')
        .post((req, res) => {

            consoleLogger.info("Inside makeComment API..");
            logger.info("Inside makeComment");

            let timestamp = new Date().getTime();

            let latestCommentID = timestamp.toString();

            console.log("comment ID generated is "+latestCommentID);


            res.json({
                                'makeComment': 'success',
                                'commentid':latestCommentID
                 });

        });

现在,如果多个并发请求来到这个 API,会发生什么?

据我了解,NodeJS 会为请求维护一个事件队列,并一一处理请求。

因此,不可能为两个不同的请求获得相同的时间戳。

请让我知道我的理解是否正确?


编辑1:

谷歌搜索了一段时间后,得到了这个链接,它清楚地解释了一些概念。

4

2 回答 2

6

您绝对可以在 2 个并发调用中获得相同的时间戳。但不是因为 NodeJS 或您的服务器并行处理请求,而是因为一毫秒足够长,您的服务器可以在同一毫秒内处理许多请求。

多线程与并发

您已经正确识别出并发和多线程之间微妙但重要的区别。在多线程环境中,两个不同的操作可以真正在 CPU 的 2 个不同内核上同时进行。在并发但单线程的环境中,事情确实按顺序发生,希望以非阻塞方式发生,而且非常快!

Javascript 是一个单线程环境。是的,它有一个事件循环,它将任务排队并一次处理一个。NodeJS(以及浏览器 Javascript 应用程序中的 Web API)提供某些异步功能,例如fs.writeFilefetch,运行时与操作系统协作可以在相同或不同的线程/核心中执行,然后通过编排将结果返回给您的应用程序回调和承诺。

在您的示例中,您的处理程序(从 开始的部分(req, res) => { ... })仅包含同步调用。所以,是的,对这个处理程序的各种调用将依次运行,一个接一个。而且,虽然这个处理程序的两次运行不会真正同时发生,但它们会发生得非常快,并且您可能会遇到从 Date 对象获得相同毫秒值的情况。如果您有更高分辨率的时间戳可用(可能是纳秒),或者如果您的处理程序运行时间更长(例如,您运行了for十亿次迭代的循环),那么您将能够更清楚地观察顺序行为。

避免在单线程应用程序中阻塞(同步)调用

这就是为什么建议您不要fs.writeFileSync在 NodeJS Web 服务器中执行任何同步 IO 操作(例如,等等)的确切原因,因为当一个请求正在执行阻塞 IO 操作时,所有其他请求都在等待,并在事件循环中排队。

关于 Javascript 事件循环的非常好的视频;这应该阐明一些主题:https ://www.youtube.com/watch?v=8aGhZQkoFbQ

于 2019-06-06T05:43:27.253 回答
4

这里没有并发的可能性。正如您正确研究的那样,Node.js 在单线程环境中运行(除非您使用集群worker API或其他有助于IPC的相关 Node.js 模块)。因此,该行

let timestamp = new Date().getTime();

不能由两个同时运行的线程同时调用,上述例外除外。

但是,Date.prototype.getTime()只有毫秒分辨率,因此apiRouter.route('/makeComment').post()事件循环很可能在同一毫秒内从两个挂起的异步请求顺序调用回调。

于 2019-06-06T05:42:18.410 回答