当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

本文关键字:js 请求 Node 是什么 http 服务器 其他 长时间      更新时间:2023-09-26

当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() }

请帮我一下。如果node.js在得到响应之前不会处理请求,我看不出使用node.js的原因,所以我认为问题是由我的错误代码引起的。下面是发送http请求的类。

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;
	}
}

更新:当前流程

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。

可以增加全局代理的大小,如http.globalAgent.maxSockets = Infinity或一个高值,具体取决于您的要求,并删除您创建的自定义池

在全局级别定义自定义池并设置maxsockets

var myAPIPool = new http.Agent({"maxSockets" : Infinity}); // Infinity or a high value depending on your res.

然后在方法

中使用这个变量
var requestObj = {
            url : targetUrl,
            json : true,
            pool: myAPIPool
        }

在玩弄请求。js我来到以下实现。如果在请求模块上调用http方法,则需要使用on方法提供回调。例如。)

  request.get(requestObj).on('response', function (response){
                callback(null, body);
            });
同样,您需要提供链接此模式的错误回调。ie)。on("error',cb)

这将给你期望的行为。

更新:

我测试了以下代码,在没有任何代理的情况下对您的版本进行了轻微的调整。这清楚地记录了调用以及所有调用何时完成的日志S回调
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");