处理多个请求而不阻止下一个请求 [英] Handling multiple requests without previous one blocking the next one

查看:124
本文介绍了处理多个请求而不阻止下一个请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试处理来自客户端的多个请求时遇到问题。通过权利,每个路由应该异步处理,但是我不能在请求之后进行处理请求而没有前一个阻止下一个请求。使用以下代码我使用promises并使用Express.js路由器

I have problems trying to handle multiple requests from the client. By right, each route should be handled asynchronously, however I can't make handling request after request without the previous one blocking the next one. With the following code I am using promises and using Express.js router

  let api = Router();

  api.get('/a', (req, res, next) => {
    console.log('A: get all A');
    getAllA()
      .then(() => console.log('A: finish retrieving A'));
    console.log('A: do something else');
  });

  api.get('/b', (req, res, next) => {
    console.log('B: get all B');
    getAllB()
      .then(() => console.log('B: finish retrieving B')
    console.log('B: do something else');
  });

所以如果我要求 / a 然后 / b 几乎立即之后,输出目前是:

So if I request /a and then /b almost instantly after, the output currently is:

// Request /a
'A: get all A'
'A: do something else'
// Request /b
'A: finish retrieving A'
'B: get all B'
'B: do something else'
'B: finish retrieving B'

虽然我期待它是这样的:

// Request /a
'A: get all A'
'A: do something else'
// Request /b
'B: get all B'
'B: do something else'
'A: finish retrieving A'
'B: finish retrieving B'

是否有预期或有其他方法可以解决这个问题?

Any idea whether this is expected or there are other ways to handle this?

推荐答案

node.js服务器运行一次只执行一个Javascript线程。它实际上并不是在同一时间处理多个请求。因此,如果一个请求占用CPU一段时间,则在第一个请求完成并放弃CPU之前,不会处理任何其他请求。

A node.js server runs only one Javascript thread of execution at a time. It does not actually process multiple requests at the exact same time. So, if one request hogs the CPU for awhile, no other requests will get processed until that first request finishes and gives up the CPU.

但是,如果您的请求执行异步操作操作(异步文件I / O,异步网络,设置定时器以便将来做某事,使用一些实现其他异步操作的第三方库等等),然后每当请求启动异步操作并返回控制权时到事件队列,然后另一个请求可以开始处理,直到它完成或也命中异步操作。它是否完全取决于事物的时间安排。通过这种方式,多个请求可以同时在飞行中,即使一次只有一个实际运行Javascript。

But, if your requests do async operations (async file I/O, async networking, set timers to do something in the future, use some third party library that implements some other async operation, etc...), then whenever a request starts an async operation and returns control back to the event queue, then another request can start processing until it finishes or also hits an async operation. Whether it does or doesn't will depend entirely on the timing of things. In this way, multiple requests can be "in-flight" at the same time, even though only one is ever actually running Javascript at a time.

所以,在你的代码,它实际上取决于 getAllA() getAllB()正在做什么。如果它们是同步操作,那么它们将在运行时阻止其他线程。如果它们是异步操作,但它们内容相同的资源(例如数据库或文件或服务器),那么它们可能仍然会导致某些序列化,因为它们依赖于外部资源的可用性。

So, in your code, it really depends upon what getAllA() and getAllB() are doing. If they are synchronous operations, then they will block other threads while they run. If they are asynchronous operations, but they content for the same resources (such as a database or file or server), then they may still cause some serialization because of the mutual dependency upon the availability of an external resource.

在node.js中获得真正的并行请求处理的一种方法是使用群集。使用node.js群集,您可以在同一台计算机上启动多个node.js进程(通常与您拥有的CPU核心数量大致相同),然后每个node.js进程可以独立地并行处理请求。如果您拥有群集中所有进程必须访问的共享资源,那么您仍然必须找到一种方法来跨进程共享这些资源(数据库,共享信息的自定义中央存储库,redis等等。)。

One way to get true parallel request processing in node.js is with clustering. With node.js clustering, you start up multiple node.js processes on the same computer (usually about the same number of processes as CPU cores you have) and then each node.js process can independently process requests in parallel. If you have shared resources that all the processes in the cluster must access, then you will still have to find a way to share those across processes (database, custom central repository of shared info, redis, etc..).

例如,如果你做了类似的事情,你可以在同一时间看到多个飞行请求:

For example, you could see multiple requests in flight at the same time if you did something like this:

let api = Router();

api.get('/a', (req, res, next) => {
    console.log('start of a');
    setTimeout(function() {
        console.log('done with a');
        res.json({status: "ok", msg: "done with a"});
    }, 500);
});

api.get('/b', (req, res, next) => {
    console.log('start of b');
    setTimeout(function() {
        console.log('done with b');
        res.json({status: "ok", msg: "done with b"});
    }, 500);
});

如果你然后一个接一个地关闭/ a和/ b的请求,你应该得到这在服务器控制台中:

If you then fire off requests for /a and for /b right after one another, you should get this in the server console:

start of a
start of b
done with a
done with b

两个请求同时在飞行中,但实际上没有执行Javascript同时。注意:我使用 setTimeout()只是为了模拟具有已知和可控响应时间的异步操作。这可以是任何系列的异步操作。

Both requests were "in-flight" at the same time, though not actually executing Javascript at the same time. Note: I used setTimeout() just to simulate an async operation with a known and controllable response time. That can be any series of asynchronous operations.

这篇关于处理多个请求而不阻止下一个请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆