Node.js是否逐个处理客户端请求?

时间:2015-08-18 03:21:00

标签: javascript node.js httprequest

Node.js是否逐个处理客户端请求?我有一个项目,它使用Node.js作为服务器端代理。根据我的理解,如果您使用回调进行响应,Node.js应该毫不拖延地响应新请求,但实际上Node.js不会响应新请求,直到完成最后一次回调为止。这是正确的操作还是有一些不正确的代码使用?请帮帮我。非常感谢你。以下是将请求重新发送到后端服务的代码。

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



Current process

client       request1  ->       Node
client       request2  ->       Node
                                Node    server request1    ->backend
                                Node (waiting for event loop)
                                Node     <- server response1 backend
client       <- response1       Node
                                Node    server request2    ->backend
                                Node     <-  server response2 backend
client       <- response2       Node 
What I think it should be

  client       request1  ->       Node
client       request2  ->       Node
                                Node    server request1 ->     backend
                                Node (won't waiting for event loop)
                                Node    server request2 ->     backend
                                Node    <- server response2    backend
client       <-response2        Node
                                Node    <- server response1    backend 
client       <-response1        Node
&#13;
&#13;
&#13;

更新

&#13;
&#13;
               var params = {
						action : 'list'
				};
				$http.post('../../service/buildingBlockService', params)
				.success(function(buildingBlocks){
						callback(null, buildingBlocks);
					}).error(function(error){
						callback(error);
					})
&#13;
&#13;
&#13;

客户端请求来自Angular $http。在一个页面上,同时有几个请求。根据我的Fiddler监视器,来自浏览器的请求无需等待即可发送,但服务器重新发送是一个接一个。

&#13;
&#13;
app.post('/service/buildingBlockService', function (ctx, payload, req, res) {  
		var service1 = require('./service/buildingBlockService');
		var service = new service1();
		service.service(ctx, payload, function(error, result){
			res.send(200, result);
		});
	});
	
&#13;
&#13;
&#13;

已更新:服务器请求的中间层。

&#13;
&#13;
var service = require('./apiService');

function BuildingBlockService(){
}

BuildingBlockService.prototype.init = function(){}

BuildingBlockService.prototype.service = function(context, payload, callback) { 
	var apiService = new service() 
	var params = payload;
	switch (params.action){
		case "list":
		default:
			apiService.get(context, null, callback, "BuildingBlocks");
			break;
	}
	 
};  
  
module.exports = BuildingBlockService;  
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:7)

  

Node.js是否逐个处理客户端请求?

是和否.node.js运行您的JS单线程。这意味着在任何给定时间只运行一个JS执行线程。所以,如果您有两个这样的请求:

// don't use this in real code, it's to simulate a point
function spin(t) {
    var start = Date.now();
    while (Date.now() < start + t) {}
}

app.post("/route1", req, res) {
    console.log("starting processing of /route1 request");
    // simulate taking several seconds of pure CPU to make a response
    spin(2000);
    res.send("done 1");
    console.log("finished processing of /route1 request");
}

app.post("/route2", req, res) {
    console.log("starting processing of /route2 request");
    // simulate taking several seconds of pure CPU to make a response
    spin(2000);
    res.send("done 2");
    console.log("finished processing of /route2 request");
}

并且/ route1请求之后紧跟一个/ route2请求,然后node.js服务器将处理/ route1请求,并且在完成该请求之前无法执行任何其他操作,因为CPU保持忙碌整个时间。

所以,这会产生这样的日志:

starting processing of /route1 request
finished processing of /route1 request
starting processing of /route2 request
finished processing of /route2 request

但是,由于CPU原因,请求需要很长时间才是相对罕见的。通常请求涉及某种I / O(要读取的文件,数据库查询,要联系的其他服务器等等)。如果使用异步IO并且不使用同步IO以异步方式完成I / O,那么多个请求可以同时轻松地在飞行中并且将同时在飞行中,因为node.js服务器正在等待要完成I / O请求,可以免费提供其他请求并提供其他请求。

所以,如果你有这个服务器代码:

app.post("/route1", req, res) {
    console.log("starting processing of /route1 request");
    // simulate taking several seconds of pure CPU to make a response
    request('http://www.google.com', function (error, response, body) {
        if (!error && response.statusCode == 200) {
            res.send("done 1");
            console.log("finished processing of /route1 request");
        }
    });
}

app.post("/route2", req, res) {
    console.log("starting processing of /route2 request");
    // simulate taking several seconds of pure CPU to make a response
    request('http://www.google.com', function (error, response, body) {
        if (!error && response.statusCode == 200) {
            res.send("done 2");
            console.log("finished processing of /route2 request");
        }
    });
}

并且/ route1请求之后紧跟一个/ route2请求,然后您可能会看到此日志(/ route1和/ route2响应完成的顺序无法保证 - 它们可以按任何顺序排列),但两者都有回复将同时处理:

starting processing of /route1 request
starting processing of /route2 request
finished processing of /route1 request
finished processing of /route2 request

如果您的node.js代理服务器似乎表现出串行处理行为而不是并行处理行为,那么可能是因为它实现代理的方式存在某种实现问题,因为它当然能够具有多个请求同时在飞行中。