节点服务器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秒钟。
但是这不是你真正的设置将会做的,除非你使用的其他技术也是单线程的。 (如果是这样,你可能希望有多个并行运行。)