0

我有一个打开 8000 端口的 node.js 服务器。它是一个聊天服务器。我有另一个 PHP 服务器,我使用代理 + 虚拟主机,所以当我去 www.phpserver.com/chat 它代理到 node.js 服务器。我这样做是为了可以使用 ajax 来调用 node.js 服务器。

现在,当我运行 node.js 服务器时一切正常,但是,过了一段时间(随机时间框架,不一定长或短),PHP 服务器会崩溃,因为它从 node.js 服务器获取 EOF 并且它一直卡在那里,直到我停止/重新启动 node.js 服务器。

我得到的错误是(来自 php 错误日志):

(70014) 找到文件结尾:代理:从远程服务器 nodeserver.com:8000 读取状态行时出错,引用者:https ://www.phpserver.com

我问了一些专业人士,他们说这是因为 PHP 服务器成功将请求发送到 node.js 服务器并收到 EOF 或未收到任何响应。我不明白如何解决它。即使node.js服务器崩溃了,我该怎么办,它不会崩溃PHP服务器?我应该摆脱代理+ajax并开始使用socket.io吗?

请指教。

谢谢!


下面是一些节点代码。

从中间件:

       this.events.addListener('update', o_.bind(function(package) {
    if(this.clear != 0){
    delete this.sessions[this.clear];
    }
        var _package = package.toJSON();
        if(package.type == 'status' && package.status == 'offline') {
            var sids = Object.keys(this.sessions), sid, sess;
            for(sid in this.sessions) {
                sess = this.sessions[sid];
                if(sess.data('username') == package.username) {
                    if(sess.listeners.length)
                        sess.send(200, {type: 'goodbye'});
                    delete this.sessions[sid];
                    break;
                }
            }
        }
    }, this));
};

Hub.prototype.destroy = function(sid, fn) {
    this.set(sid, null, fn);
};

Hub.prototype.reap = function(ms) {
    var threshold = +new Date - ms,
        sids = Object.keys(this.sessions);
    for(var i = 0, len = sids.length; i < len; ++i) {
        var sid = sids[i], sess = this.sessions[sid];
        if(sess.lastAccess < threshold) {
         this.events.emit('update', new packages.Offline(sess.data('username')));
        }
    }
};


Hub.prototype.get = function(req, fn) {
    if(this.sessions[req.sessionID]) {
        fn(null, this.sessions[req.sessionID]);
    } else {
        this.auth.authenticate(req, o_.bind(function(data) {
            if(data) {
                var session = new User(req.sessionID, data);
                this.set(req.sessionID, session);

                this.auth.friends(req, data, o_.bind(function(friends) {
                    var friends_copy = friends.slice();
                    o_.values(this.sessions).filter(function(friend) {
                        return ~friends.indexOf(friend.data('username'));
                    }).forEach(function(friend) {
                        var username = friend.data('username');
                        friends_copy[friends_copy.indexOf(username)] =
                                            [username, friend.status()];
                    }, this);

                    session._friends(friends_copy);
            console.log("refreshed");
                    session.events.addListener('status',
                        o_.bind(function(value, message) {
                            this.events.emit(
                                'update',
                                new packages.Status(session.data('username'),
                                                    value,
                                                    message)
                            );
                        }, this));
                    this.events.addListener('update',
                                      o_.bind(session.receivedUpdate, session));
                    this.set(req.sessionID, session);
                    fn(null, session);
                }, this));
            } else {
                fn();
            }
        }, this));
    }
};

来自 app.js

    #!/usr/bin/env node
var sys = require('sys'),
    express = require('express'),
    packages = require('./libs/packages'),
    fs = require('fs'),
    o_ = require('./libs/utils'),
    https = require('https');

o_.merge(global, require('./settings'));
try { o_.merge(global, require('./settings.local')); } catch(e) {}

try {
    var daemon = require('./libs/daemon/daemon'),
        start = function() {
            daemon.init({
                lock: PID_FILE,
                stdin: '/dev/null',
                stdout: LOG_FILE,
                stderr: LOG_FILE,
                umask: 0,
                chroot: null,
                chdir: '.'
            });
        },
        stop = function() {
            process.kill(parseInt(require('fs').readFileSync(PID_FILE)));
        };

    switch(process.argv[2]) {
        case 'stop':
            stop();
            process.exit(0);
        break;

        case 'start':
            if(process.argv[3])
                process.env.EXPRESS_ENV = process.argv[3];
            start();
        break;

        case 'restart':
            stop();
            start();
            process.exit(0);
        break;

        case 'help':
            sys.puts('Usage: node app.js [start|stop|restart]');
            process.exit(0);
        break;
    }
} catch(e) {
    sys.puts('Daemon library not found! Please compile ' +
             './libs/daemon/daemon.node if you would like to use it.');
}
var options = {
  key: fs.readFileSync('/home/ec2-user/key.pem'),
  cert: fs.readFileSync('/home/ec2-user/cert.pem'),
  ca: fs.readFileSync('/home/ec2-user/ca.pem'),
};

var app = express();

//app.set('env', 'development');
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(require('./middleware/im')({
   maxAge: 30 * 1000,
   reapInterval: 20 * 1000,
   authentication: require('./libs/authentication/' + AUTH_LIBRARY)
}));

app.set('root', __dirname);

if ('development' == app.get('env')) {
    app.set('view engine', 'jade');
    app.set('views', __dirname + '/dev/views');

    app.stack.unshift({
        route: '/dev',
        handle: function(req, res, next) {
            req.dev = true;
            next();
        }
    });

    app.use(express.logger());
    require('./dev/app')('/dev', app);
    app.use(express.static(
                require('path').join(__dirname, '../client')));
    app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
}

//app.listen(APP_PORT, APP_HOST);

// Listener endpoint; handled in middleware
app.get('/listen', function(){});

app.post('/message', function(req, res) {
    res.find(req.body['to'], function(user) {
        if(!user)
            return res.send(new packages.Error('not online'));

        res.message(user, new packages.Message(
            req.session.data('username'),
            req.body.body
        ));
    });
});

app.post('/message/typing', function(req, res) {
    if(~packages.TYPING_STATES.indexOf('typing' + req.body['state'])) {
        res.find(req.body['to'], function(user) {
            if(user) {
                res.message(user, new packages.Status(
                    req.session.data('username'),
                    'typing' + req.body.state
                ));
            }

            // Typing updates do not receive confirmations,
            // as they are not important enough.
            res.send('');
        });
    } else {
        res.send(new packages.Error('invalid state'));
    }
});

app.post('/status', function(req, res) {
    if(~packages.STATUSES.indexOf(req.body['status'])) {
        res.status(req.body.status, req.body.message);
        res.send(new packages.Success('status updated'));
    } else {
        res.send(new packages.Error('invalid status'));
    }
});


app.post('/online', function(req, res) {
var d = new Date();
var n = d.getTime() + 30;
req.sessionID.expires = n;
res.status(req.body.status, 'available');
});


app.post('/signoff', function(req, res) {
    res.signOff();
    res.send(new packages.Success('goodbye'));
});


app.use(function(err, req, res, next){
  console.error(err.stack);
  res.send(500, 'Error on the node/express server.');
});


https.createServer(options, app).listen(8000);
4

1 回答 1

0

我无法帮助您回答您的问题,但我可以尝试为您指明正确的方向。

我自己目前正在使用 Node JS 服务器,我发现设置记录器非常有用。

其中有几个,但到目前为止我最喜欢的是温斯顿。

参考:https ://github.com/flatiron/winston

为您的 Node JS 服务器安装 Winston(似乎您已经安装了一些模块):

npm install winston

然后我将记录器模块设置为(logger.js):

/**
 * Usage:
 *  - logger.info('sample text');
 *  - logger.warn('sample text');
 *  - logger.error('sample text');
 */

// Load modules
var winston = require('winston');

// Create custom logger
var logger = new (winston.Logger)({
    transports: [
        new (winston.transports.Console)({ json: false, timestamp: true }),
        new winston.transports.File({ filename: __dirname + '/debug.log', json: false })
    ],
    exceptionHandlers: [
        new (winston.transports.Console)({ json: false, timestamp: true }),
        new winston.transports.File({ filename: __dirname + '/exceptions.log', json: false })
    ],
    exitOnError: false
});

// Export logger
module.exports = logger;

最后,我通过以下方式将 Winston 记录器模块加载到我的服务器脚本中:

var logger = require('./logger');

它会自动将任何异常记录到的 Node JS 服务器位置上的 exceptions.log 中。在与 PHP 无关的 Node JS 中捕获我之前没有注意到的异常对我有很大帮助。

PS 另请查看 socket.io,这可能会简化您尝试做的事情。

于 2013-10-01T23:04:35.533 回答