Node.js异步并发PHP执行

时间:2015-08-26 02:45:02

标签: javascript php node.js asynchronous concurrency

我正在创建一个混合node.js和php系统。我目前正在研究一个并发问题,当node.js执行php脚本时似乎存在碰撞问题,但我不确定是否是这种情况。考虑一下我的源代码:

node.js代码:(async-test.js)

var exec = require('child_process').exec,
    async = require('async');

cmd = "php echo.php";
// log("cmd: "+cmd);


Util = {
  execute : function(obj, callback){
    exec(cmd, function(error, stdout, stderr) {
      obj.out = stdout;
      callback(obj);
    });
  },
  uniqid : function() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }

    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
  }
};

/**
 * scenario 1: execute immediately in foreach loop
 */
function scenario_1(num_executions) {
  for (var i = 0; i < num_executions; i++) {
    obj = {
      id : Util.uniqid()
    }

    console.time("php echo.php: "+obj.id);
    Util.execute(obj, function(obj){
      console.timeEnd("php echo.php: "+obj.id);
    });
  } 
}

/**
 * scenario 2: execute using async module
 */
function scenario_2(num_executions) {
  tasks = [];
  for (var i = 0; i < num_executions; i++) {
    task = function(){
      obj = {
        id : Util.uniqid()
      }

      console.time("php echo.php: "+obj.id);
      Util.execute(obj, function(obj){
        console.timeEnd("php echo.php: "+obj.id);
      });
    }

    tasks.push(task);
  }

  async.parallel(tasks); 
}

php code:(echo.php)

<?php 
echo "something done!";
?>

如您所见,我的目标是node.js将同时运行多个php脚本。然而,问题是当执行多个或多于1个php脚本时,php脚本的执行持续时间会叠加。以下是场景:

scenario_1(5):
php echo.php: 4f6140f2-cb89-4c54-d75a-0814370661d5: 645ms
php echo.php: aac0a659-1ef5-29c6-37e8-bc6c59bfeeea: 657ms
php echo.php: c34a4368-82b9-10ad-9add-59b321f03d91: 656ms
php echo.php: 17bc6134-f57c-227f-720d-89b21867af0e: 868ms
php echo.php: 134065e2-ea4f-e9a9-0166-d1999d74cb1d: 944ms

scenario_1(10):
php echo.php: c8c55c6e-df10-9c66-1b7d-8e866b0f5a0c: 1242ms
php echo.php: 9b75d915-2615-0092-bff1-ca1bb09cc3c5: 1254ms
php echo.php: 0c5cc8d9-219d-3e4b-ac7f-f0f533035a7a: 1261ms
php echo.php: fed597e5-c5fa-a064-f1b7-6ad7a2f5797d: 1266ms
php echo.php: 8e09ebb0-55f0-15fc-c1b2-444997c352cc: 1282ms
php echo.php: ae0eb4e0-0031-d056-6a0a-4d476b69bf5d: 1265ms
php echo.php: 23e356a9-7f0d-c0f3-f659-ca13255b0e12: 1326ms
php echo.php: 195313ee-963d-5dac-d4af-55c089b4b749: 1448ms
php echo.php: e5557819-9a49-b58c-ba4f-c87b878f0ba5: 1816ms
php echo.php: 04034c39-d120-8a67-e634-6bb16859409e: 1827ms

scenario_2(1):
php echo.php: faf1a9f7-900d-f757-7cd8-52d3a61328b0: 560ms

scenario_2(5):
php echo.php: 013743b0-47e0-b1d8-2c72-becd7d880832: 636ms
php echo.php: b1e6f53f-5a92-a459-db88-b3c2e36d920d: 646ms
php echo.php: b78550d3-bee8-38c8-3730-ba45706545d4: 710ms
php echo.php: 0a1a0c25-5114-07f8-54d3-ee43b71f9a7e: 900ms
php echo.php: a65bde54-103d-446e-3435-46cb2a30e304: 912ms

scenario_2(10):
php echo.php: c6af334b-af87-3a14-2fc4-1a64a584fe13: 1222ms
php echo.php: 4495203d-eddd-37d3-e29c-9a8c04b85c36: 1240ms
php echo.php: a4344b25-5095-337f-aee6-8bab68f8693f: 1257ms
php echo.php: fbbe9e58-f7ff-1cc9-ab1a-a4b9ebe6f97a: 1304ms
php echo.php: 981eb8a4-e705-062a-30ab-0960f3937c30: 1317ms
php echo.php: 0e032ddf-6844-2a90-5781-3dd66392e5e0: 1355ms
php echo.php: 62180284-9987-8f19-8ae6-ef5e5538db22: 1375ms
php echo.php: 96895ee1-c750-fdec-da9f-d5759017f0f0: 1386ms
php echo.php: fe86da3f-827c-df64-485c-93ecf0eaf74f: 1424ms
php echo.php: 2edef0ec-580d-0148-c889-5ef77ab062e1: 1557ms

scenario_2(20):
php echo.php: b5c42915-3d6b-8119-5eed-6142f0a22f1f: 782ms
php echo.php: aa493142-bc6b-9f47-7812-6f6ba8840968: 793ms
php echo.php: 73b33e76-6777-4236-b7c7-faccb55273b8: 811ms
php echo.php: 814e2db2-8b20-b8ce-1c69-f8cdfd879b76: 809ms
php echo.php: a41c5696-5cc7-5a69-bdbe-c5233b918301: 2283ms
php echo.php: 2d171035-7898-ebaa-af5b-8836dc4ad543: 2211ms
php echo.php: c76b9d4a-c4cb-2617-77d4-ec1afb6b2aff: 2270ms
php echo.php: 0f117dd5-3d87-e43f-81be-d65974c2e396: 2196ms
php echo.php: 2b0318c4-b86d-bb3a-612c-c457cf37f436: 2299ms
php echo.php: a3b4ca39-e26c-612b-6435-d3ba199321fa: 2309ms
php echo.php: 9eccd022-f2de-b8ee-2572-139b1bf6efb3: 2289ms
php echo.php: 75c0cd8d-881e-6925-b89a-933bf1d9be5e: 2307ms
php echo.php: f082c8cd-08ac-70e0-1888-23015bb021ed: 2413ms
php echo.php: a1ab50c3-d7ac-b0da-5e9b-26728547df51: 2439ms
php echo.php: 83a85b6d-236a-265d-3a6f-fdf065c7a486: 2328ms
php echo.php: a4dc49c1-b4a5-ca18-a1cd-fa0dcd36f9cd: 2464ms
php echo.php: 666778e2-ed20-32d9-6df7-592d3bbe5059: 2414ms
php echo.php: b97cb8fe-086f-46aa-31da-37c6aede69d9: 2388ms
php echo.php: 5ba386cb-352d-a2f2-2328-7a132c51b14b: 2473ms
php echo.php: 888bc9aa-bff5-7f14-846a-a6d847db44e6: 2779ms

这是我的问题: 有没有办法同时优化PHP脚本的运行?因为当我只运行scenario_2(1)时,您可以看到单个脚本的总执行时间是560毫秒,但是当我运行具有10个或更多执行的方案2时,您可以看到执行时间超过一秒!我还使用了node.js的异步模块,但它仍然是相同的。

另外,考虑到正在执行的php脚本只回显一个简单的字符串,但为什么在node.js中同时执行10个以上的字符串需要一秒多的时间?

即使我有10个或更多的同时执行,有没有办法让每个PHP脚本执行500+毫秒?

1 个答案:

答案 0 :(得分:2)

只是从评论中发布@jfriend00&#39的解决方案;我已经实现了一个http请求,而不是通过cli运行php脚本。

这里是node.js的更新源代码:(async-test.js)

var exec = require('child_process').exec,
    async = require('async'),
    http = require('http');

cmd = "php echo.php";
// log("cmd: "+cmd);

Util = {
  execute : function(method, obj, callback){
    if (method == "cli") {
      /**
       * cli implementation
       */
      exec(cmd, function(error, stdout, stderr) {
        obj.out = stdout;
        callback(obj);
      });
    }else if(method == "curl"){
      /**
       * curl implementation
       * note: echo.php file is located in the htdocs folder
       *       and running an apache/httpd server
       */
      http.get({
        host : "localhost",
        port : 80,
        path : "/echo.php",
        method : "get"
      }, function(resCurl){
        var data = "";

        resCurl.on('data', function(chunk){
          data += chunk;
        });

        resCurl.on('end', function(){
          obj.out = data;
          // console.log({response : data});
          callback(obj);
        });
      });
    }
  },
  uniqid : function() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }

    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
  }
};

/**
 * scenario 1: execute immediately in foreach loop
 */
function scenario_1(method, num_executions) {
  for (var i = 0; i < num_executions; i++) {
    obj = {
      id : Util.uniqid()
    }

    console.time("php echo.php: "+obj.id);
    Util.execute(method, obj, function(obj){
      console.timeEnd("php echo.php: "+obj.id);
    });
  } 
}

/**
 * scenario 2: execute using async module
 */
function scenario_2(method, num_executions) {
  tasks = [];
  for (var i = 0; i < num_executions; i++) {
    task = function(){
      obj = {
        id : Util.uniqid()
      }

      console.time("php echo.php: "+obj.id);
      Util.execute(method, obj, function(obj){
        console.timeEnd("php echo.php: "+obj.id);
      });
    }

    tasks.push(task);
  }

  async.parallel(tasks); 
}

这是更新的方案

scenario_1("curl", 10):
php echo.php: 6d01308f-b0ab-8046-bbf6-87380d92aa81: 11ms
php echo.php: 09594593-e44f-76f6-8895-25dfdbaa9a23: 9ms
php echo.php: f1893c6f-f268-a909-f5c8-557a2040281b: 10ms
php echo.php: 29777ae7-97f5-9a58-10cc-0a7e7385ee68: 10ms
php echo.php: 5814ca5f-9b45-fe21-1882-fd8486c9e566: 11ms
php echo.php: 65b48d31-007c-d25f-199a-dfb7cc7a873c: 11ms
php echo.php: b2c69a49-d7c1-ffb6-bc9c-9a6e07d51840: 12ms
php echo.php: cebf2b11-d704-f260-2e0b-ec9d261d8e9a: 13ms
php echo.php: 254963bd-7143-850e-fdbd-fae444617c7b: 13ms
php echo.php: 3e5f35b9-bb7f-fcf7-877e-5cd4a895e55d: 14ms

scenario_2("curl", 10):
php echo.php: 54564c27-f48b-c69d-9e3c-4473ea8f7135: 10ms
php echo.php: 57f07115-c02f-16a7-7b46-ec0480d32ec9: 9ms
php echo.php: 6f0d7611-c3a8-574a-dd28-30d2d78c50c0: 9ms
php echo.php: b17f3d63-b9a7-761c-6cb4-a3e9113abf04: 11ms
php echo.php: 60b90263-6bd2-df6b-b8ca-9979fe4dd998: 11ms
php echo.php: a341284b-f791-9dbb-fad1-ef4422ba075f: 11ms
php echo.php: 6964f00a-52e3-ad7f-1051-b263baecf928: 12ms
php echo.php: d096e0ed-5d1f-2e06-6ff3-31d6379c522a: 12ms
php echo.php: 3e357403-541c-acd1-1b7f-da7c2d463fb2: 13ms
php echo.php: a517273f-7412-b818-d3ec-c8b1c706eaa0: 13ms

http解决方案解决了问题

来自@ jfriend00的评论:

  

注意:如果没有很多PHP代码在运行,那么您的任务可能就是   主要是启动/关闭开销。它可能更有意义   有几个PHP服务器正在运行,只是提供他们的请求。您   将避免启动,加载,解析脚本和所有开销   然后退出PHP进程。