phantomjs-node crashes when attempting to scale behind node-cluster

你。 提交于 2019-12-10 18:35:32

问题


Associated GitHub issue: https://github.com/sgentle/phantomjs-node/issues/280

I have a simple app that does the following:

var
    phantom = require('phantom'),
    express = require('express'),
    serve = express();

serve.get('/foo', function (req, res) {
    try {
        phantom.create(function (ph) {
            console.log('Phantom browser created w/ pid: ', ph.process.pid);
            ph.onError = function (msg, trace) {
                var msgStack = ['PHANTOM ERROR: ' + msg];
                if (trace && trace.length) {
                    msgStack.push('TRACE:');
                    trace.forEach(function (t) {
                        msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
                    });
                }
                console.log(msgStack.join('\n'));
            };
            ph.createPage(function(page){
                page.open('http://www.stackoverflow.com', function(status){
                    res.json({pageStatus: status});
                    page.close();
                    ph.exit();
                });
            });
        });
    } catch(e){
        console.log(e);
        throw e;
    }

});

As long as I run this in WebStorm, it runs just fine and I can hit the /foo endpoint w/ as many concurrent requests as I want and everything works as expected.

But as soon as I try to scale it behind PM2 w/ pm2 start -i 0 phantomapp.js, everything still works fine as long as I don't throw too many requests at it. The second I open up two browser windows and hit refresh in both, I get the following in pm2 logs. At which point, ALL 8 processes managed by PM2 just "disappear"! What am I doing wrong?? :

PM2: 2015-05-27 18:53:17: [PM2] Error caught by domain:
PM2: AssertionError: false == true
PM2:     at RoundRobinHandle.add (cluster.js:140:3)
PM2:     at queryServer (cluster.js:480:12)
PM2:     at Worker.onmessage (cluster.js:438:7)
PM2:     at ChildProcess.<anonymous> (cluster.js:692:8)
PM2:     at ChildProcess.emit (events.js:129:20)
PM2:     at handleMessage (child_process.js:324:10)
PM2:     at Pipe.channel.onread (child_process.js:352:11)
PM2: 2015-05-27 18:53:18: [PM2] Automatic `pm2 update` failed. Killing PM2 daemon and its processes...
PM2: 2015-05-27 18:53:18: pm2 has been killed by signal, dumping process list before exit...
PM2: 2015-05-27 18:53:18: Stopping app:phantomapp id:0
PM2: assert.js:86
PM2:   throw new assert.AssertionError({
PM2:         ^
PM2: AssertionError: false == true
PM2:     at RoundRobinHandle.add (cluster.js:140:3)
PM2:     at queryServer (cluster.js:480:12)
PM2:     at Worker.onmessage (cluster.js:438:7)
PM2:     at ChildProcess.<anonymous> (cluster.js:692:8)
PM2:     at ChildProcess.emit (events.js:129:20)
PM2:     at handleMessage (child_process.js:324:10)
PM2:     at Pipe.channel.onread (child_process.js:352:11)
phantomapp-0 (err): Process disconnected from parent !
PM2: [PM2] Spawning PM2 daemon
PM2: 2015-05-27 18:53:18: [PM2][WORKER] Started with refreshing interval: 30000
PM2: 2015-05-27 18:53:18: [[[[ PM2/God daemon launched ]]]]
PM2: 2015-05-27 18:53:18: BUS system [READY] on port /Users/matthewmarcus/.pm2/pub.sock
PM2: 2015-05-27 18:53:18: RPC interface [READY] on port /Users/matthewmarcus/.pm2/rpc.sock
PM2: [PM2] PM2 Successfully daemonized
PM2: Be sure to have the latest version by doing `npm install pm2@latest -g` before doing this procedure.
PM2: [PM2] Stopping PM2...
PM2: [PM2][WARN] No process found
PM2: [PM2] All processes have been stopped and deleted
PM2: 2015-05-27 18:53:18: PM2 is being killed via kill method
PM2: 2015-05-27 18:53:18: RPC socket closed
PM2: 2015-05-27 18:53:18: PUB socket closed
PM2: [PM2] PM2 stopped
PM2: 2015-05-27 18:53:19: [PM2][WORKER] Started with refreshing interval: 30000
PM2: 2015-05-27 18:53:19: [[[[ PM2/God daemon launched ]]]]
PM2: 2015-05-27 18:53:19: BUS system [READY] on port /Users/matthewmarcus/.pm2/pub.sock
PM2: 2015-05-27 18:53:19: RPC interface [READY] on port /Users/matthewmarcus/.pm2/rpc.sock
PM2: >>>>>>>>>> PM2 updated
PM2: ┌──────────┬────┬──────┬─────┬────────┬─────────┬────────┬────────┬──────────┐
PM2: │ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │
PM2: └──────────┴────┴──────┴─────┴────────┴─────────┴────────┴────────┴──────────┘
PM2:  Use `pm2 show <id|name>` to get more details about an app

You can reproduce the same issue using node-native cluster:

var cluster = require('cluster');

if(cluster.isMaster){
    var cpuCount = require('os').cpus().length;

    for (var i = 0; i < cpuCount; i++){
        cluster.fork();
    }

    cluster.on('exit', function(worker){
        console.log('Worker ' + woker.id + ' died. Forking...');
        cluster.fork();
    });

} else {
    var
        phantom = require('phantom'),
        express = require('express'),
        serve = express();

    serve.get('/foo', function (req, res) {
        try {
            phantom.create(function (ph) {
                console.log('Phantom browser created w/ pid: ', ph.process.pid);
                ph.onError = function (msg, trace) {
                    var msgStack = ['PHANTOM ERROR: ' + msg];
                    if (trace && trace.length) {
                        msgStack.push('TRACE:');
                        trace.forEach(function (t) {
                            msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
                        });
                    }
                    console.log(msgStack.join('\n'));
                };
                ph.createPage(function(page){
                    page.open('http://www.stackoverflow.com', function(status){
                        res.json({pageStatus: status});
                        page.close();
                        ph.exit();
                    });
                });
            });
        } catch(e){
            console.log(e);
            throw e;
        }

    });
}

Which produces the following error in the console when attempting to handle > 1 request concurrently:

assert.js:86
  throw new assert.AssertionError({
        ^
AssertionError: false == true
    at RoundRobinHandle.add (cluster.js:140:3)
    at queryServer (cluster.js:480:12)
    at Worker.onmessage (cluster.js:438:7)
    at ChildProcess.<anonymous> (cluster.js:692:8)
    at ChildProcess.emit (events.js:129:20)
    at handleMessage (child_process.js:324:10)
    at Pipe.channel.onread (child_process.js:352:11)

回答1:


I tried with this gist and I'm able to create the phantom browser and to get a response.

  • If I run two tabs on localhost:3000/foo, the second will be spawned only when the first has ended.
  • If I run more than two concurrent requests in my browser (chrome), I get the error too.
    • If I try to run more requests (from a bash) than the number of clusters it crashes.
  • If I run requests (less than or equal to the number of cluster) from a bash script it doesn't crash at all.

    Also, I'm noticing that with the bash script I'm running everything in concurrence:

    http GET localhost:3000/foo &
    http GET localhost:3000/foo &
    http GET localhost:3000/foo &
    http GET localhost:3000/foo &
    

The error you're seeing comes from this assertion:

  assert(worker.id in this.all === false);

Meaning that the worker is not in the round robin anymore.

I don't think that this is direclty related to PM2 but there is a bug. PM2 should not crash. I suggest your report an issue by quoting this stackoverflow. Not sure that it can be fixed if it's a node bug though.

Sadly there are no fix for this at the moment but you can take a look at a nodejs issue. I've read that iojs fixed this, maybe you can give it a try ;).

Another related stackoverflow: NodeJS Cluster unexpected assert.AssertionError.



来源:https://stackoverflow.com/questions/30496072/phantomjs-node-crashes-when-attempting-to-scale-behind-node-cluster

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!