当Node.js为其他服务器请求长时间的http请求时,Node.js的正确行为是什么 [英] What is the correct behavior for Node.js while Node.js is requesting a long time http request for other servers
问题描述
当Node.js请求长时间的http请求时,Node.js的正确行为是什么。
情况是,我的node.js服务器就像客户端和数据库层之间的Web代理(由Web服务公开)。客户端将同时向Node.js发送许多请求,node.js将使用request.js将请求传递给Web服务。一些Web服务需要几秒钟才能得到响应。因为响应的处理程序在request.js中使用回调方式,所以它应该被推送到事件循环中,并且node.js应该移动以移交新请求并且不会等待响应。但是在我的应用程序中,node.js在获取上一个响应之前不会处理新请求。我不确定哪一个是正确的行为。
对于request.js,我在选项中添加了一个代理,以避免被默认套接字阻塞。
var requestObj = {
url:targetUrl,
json:true,
pool:new http.Agent()
}
what is the correct behavior for Node.js while Node.js is requesting a long time http request.
The situation is that, my node.js server acts just like a web proxy between client side and db layer(which is exposed by web service). The client will send many requests to Node.js at the same time, the node.js will use request.js pass the requests to the web service. Some of the web services need seconds to get response. Because the handler of response is using callback way in request.js, it should be pushed into the event loop, and the node.js should move to hand over the new request and won't wait for the response. But in my application, the node.js won't process the new request until get the previous response. I am not sure which one is the correct behavior.
For the request.js, I have added a agent in option to avoid blocked by default socket.
var requestObj = {
url : targetUrl,
json : true,
pool: new http.Agent()
}
请帮我解决这个问题。如果node.js在获得响应之前不会处理请求,我看不到使用node.js的原因,所以我认为问题是由我的错误代码引起的。以下是发送http请求的类。
Please help me on this. If the node.js won't process request until get response, I can't see the reason to use node.js, so I think the issue is caused by my incorrect code. Below are the class to send http request.
var request = require('request');
var http = require('http');
function apiService(){}
apiService.prototype.get = function (context, payload, callback, url){
return this.requestAPI(context, payload, callback, url, "GET");
}
apiService.prototype.post = function(context, payload, callback, url){
return this.requestAPI(context, payload, callback, url, "POST");
}
apiService.prototype.del = function(context, payload, callback, url){
return this.requestAPI(context, payload, callback, url, "DELETE");
}
apiService.prototype.requestAPI = function(context, payload, callback, url, method){
var config = context.config;
var targetUrl = config.APIHost
+ (config.port == null ? "": (":" + config.port))
+ "/"
+ config.baseDir
+ "/"
+ url;
var requestObj = {
url : targetUrl,
json : true,
pool: new http.Agent()
}
if (config.proxy != null){
requestObj.proxy = config.proxy;
}
switch (method){
case "POST":
requestObj.body = payload;
request.post(requestObj, function (err, resp, body){
if (err){
callback(err);
return;
}
callback(null, body);
});
break;
case "GET":
var queryString = "";
for (att in payload){
if (queryString != "")
queryString += "&";
queryString += att.toString() + "=" + payload[att];
}
if (queryString!="")
requestObj.url += "?" + queryString;
request.get(requestObj, function (err, resp, body){
if (err){
callback(err);
return;
}
callback(null, body);
});
break;
case "DELETE":
requestObj.body = payload;
request.del(requestObj, function (err, resp, body){
if (err){
callback(err);
return;
}
callback(null, body);
});
break;
}
}
已更新:
当前流程
Updated: Current process
client request1 -> Node
client request2 -> Node
Node server request1 ->backend
Node <- server response1 backend
client <- response1 Node
Node server request2 ->backend
Node <- server response2 backend
client <- response2 Node
我认为它应该是什么
client request1 -> Node
client request2 -> Node
Node server request1 -> backend
Node server request2 -> backend
Node <- server response2 backend
client <-response2 Node
Node <- server response1 backend
client <-response1 Node
推荐答案
您正在为requestAPI方法的每次调用创建新的代理程序实例(新池)调用。没有设置maxsockets的默认agentInstance将使用5作为其默认值。
You are creating a new agent instance (a new pool) for every invocation of requestAPI method invocation . A default agentInstance with no maxsockets set will have 5 as its default value.
您可以增加全局代理的大小,如
http.globalAgent.maxSockets
=无穷大或高值取决于您的请求并删除您创建的自定义池
You could either increase the size of the global agent as in
http.globalAgent.maxSockets
= Infinity or a high value depending on your reqs and remove the custom pool you have created
或
在全局级别定义自定义池并设置maxsockets
define the custom pool at the global level and set the maxsockets
var myAPIPool = new http.Agent({"maxSockets" : Infinity}); // Infinity or a high value depending on your res.
然后在你的方法中使用这个变量
Then use this variable inside your method
var requestObj = {
url : targetUrl,
json : true,
pool: myAPIPool
}
更新
正在处理请求。我来到了实现之后。
如果要在请求模块上调用http方法,则需要使用on方法提供回调。
例如。 )
On playing around with request.js i came to following realization . If you are calling http methods on request module, the callbacks need to be provided using the on method. eg. )
request.get(requestObj).on('response', function (response){
callback(null, body);
});
同样,您需要提供链接此模式的错误回调。 ie。)。 on(error',cb)
etc
Similarly you would need to provide error callbacks chaining this pattern. ie.) .on("error',cb)
etc
这将为您提供预期的行为。
This will give you the expected behavior.
更新:
我测试了以下代码,对您的版本进行了小调整任何代理。这清楚地记录了呼叫,当所有呼叫都完成时,log
s回调
I tested the following code, minor tweaks of your version without any proxies. This clearly logs the calls and when all the calls are finished log s the callbacks
var request = require('request');
var http = require('http');
function apiService() {}
apiService.prototype.get = function(context, payload, callback, url) {
return this.requestAPI(context, payload, callback, url, "GET");
}
apiService.prototype.post = function(context, payload, callback, url) {
return this.requestAPI(context, payload, callback, url, "POST");
}
apiService.prototype.del = function(context, payload, callback, url) {
return this.requestAPI(context, payload, callback, url, "DELETE");
}
apiService.prototype.requestAPI = function(context, payload, callback, url, method) {
var requestObj = {
url: url,
json: true,
pool: new http.Agent()
}
switch (method) {
case "GET":
request.get(requestObj, function(err, resp, body) {
if (err) {
callback(err);
return;
}
callback(null, body);
});
break;
}
}
var apicaller = new apiService();
var url = "http://google.com";
var called = 0;
var cb = function() {
console.log("called once" + (called++));
}
console.log("calling");
apicaller.requestAPI(null, null, cb, url, "GET");
console.log("calling");
apicaller.requestAPI(null, null, cb, url, "GET");
console.log("calling");
apicaller.requestAPI(null, null, cb, url, "GET");
console.log("calling");
apicaller.requestAPI(null, null, cb, url, "GET");
console.log("calling");
apicaller.requestAPI(null, null, cb, url, "GET");
这篇关于当Node.js为其他服务器请求长时间的http请求时,Node.js的正确行为是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!