Node.js 是否一一处理客户请求?

Does Node.js handle client requests one by one?

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

更新:

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

客户端请求来自 Angular $http。在一个页面上,同时有几个请求。根据我的Fiddler监控,浏览器的请求没有等待就发送了,但是服务器是一个一个的重发。

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

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

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;  

Does Node.js handle client requests one by one?

是和否。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(要读取的文件、数据库查询、要联系的其他服务器等)。如果 I/O 是使用异步 IO 而不是使用同步 IO 以异步方式完成的,那么多个请求可以很容易地同时进行,并且将同时进行,因为虽然 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 代理服务器似乎表现出串行处理行为而不是并行处理行为,那么可能是您在如何实现代理方面存在某种实现问题当然能够同时处理多个请求。