节点服务器asynchronous调用后端服务

我是Node新手,我正在写我的第一个节点服务器。 在调用后端rest服务之后,它应该通过简单的页面来获得一个简单的获取请求。

我正在使用express来pipe理请求和axios包来作出后端请求。 问题是,服务器阻塞事件循环,我有问题了解如何调用后端asynchronous。

截至目前,前端服务器一次只能pipe理一个请求! 我期望如果后端服务每次都需要10秒的时间来回答,前端服务器可以在10秒内回答两个并发请求,而不是在20秒内。

我错在哪里?

以下是前端节点代码的摘录:

app.get('/', function(req, res) { //Making the call to the backend service. This should be asynchronous... axios.post(env.get("BACKEND_SERVICE"), { "user": "some kind of input"}) .then(function(response){ //do somenthing with the data returned from the backend... res.render('homepage'); }) } 

这里是后端节点代码的提取:

 app.post('/api/getTypes', jsonParser, function (req, res) { console.log("> API request for 'api/getTypes' SLEEP"); var now = new Date().getTime(); while(new Date().getTime() < now + 10000){ /* do nothing */ } console.log("> API request for 'api/getTypes' WAKE-UP"); res.json({"types":"1"}); } 

问题在于你的忙碌等待绑定了后端服务器,使得它甚至不能开始处理第二个请求。

我假设你试图模拟获取types需要一段时间的过程。 几率是你将要做的,以获得types将asynchronous和I / O绑定(阅读文件,查询数据库等)。 要模拟这个,只需使用setTimeout

 app.post('/api/getTypes', jsonParser, function (req, res) { console.log("> API request for 'api/getTypes' SLEEP"); setTimeout(function() { console.log("> API request for 'api/getTypes' WAKE-UP"); res.json({"types":"1"}); }, 10000); }); 

这避免了后台服务器的唯一线程,使其免费开始重叠处理第二(第三,第四,…)请求。

这是Node的关键原则之一:如果你避免,不要同步做事。 :-)这就是为什么API是如此的面向asynchronous。

如果你确实发现你需要花费大量CPU资源来处理请求,那么你可以把它作为服务器的subprocess来处理,而不是在服务器进程中进行。 节点是单线程的devise,通过强调asynchronousI / O来实现非常高的吞吐量。 对于你需要做的大部分工作来说,这是非常有效的,直到它没有。 🙂


重新评论:

后端进程将被写入除了节点之外的另一种技术,它将调用一个数据库,可能需要一段时间。 我写了简单的节点rest服务来模拟。 我想了解的是,如果后端需要时间来处理请求,前端服务器将如何反应。

花费时间来处理请求和占用唯一的服务器线程忙等待(或者做大量的CPU繁重的工作)之间有很大的区别。 你的忙碌等待模型做了大量CPU繁重的工作,但是如果获得的types是Node的外部,你不会忙着等待它,你会排队callback一个asynchronous完成(等待来自subprocess的I / O,或连接到第三个服务器进程的套接字的I / O,或等待来自DB的I / O等)。 所以上面的setTimeout例子是一个更好的模型,你真的会做什么。

忙等待使前端完成,因为它是这样的:

                               后端
时间前端队列后端
 ---- ---------- --------------------- --------------- ------
 0秒请求#1 ------>接收请求#1 ----->为请求#1提取作业
 0秒请求#1 ------>接收请求#2
                                                        忙等10秒钟
 10秒得到#1返回<----------------------------------发送回应#1
                                                  ----->请求#2的工作
                                                        忙等10秒钟
 20秒得到#2回<----------------------------------发送回应#2

所以,即使前端不忙,等待20秒,因为每个请求的后端都忙于等待(无法做其他事情)10秒钟。

但是这不是你真正的设置将会做的,除非你使用的其他技术也是单线程的。 (如果是这样,你可能希望有多个并行运行。)