套接字io服务器在一定时间后冻结(似乎)?

时间:2016-01-31 19:42:05

标签: node.js socket.io

我的代码太长了,无法在此处发布,但基本上我使用socket.io服务器从数据库中提取数据并在客户端每1秒刷新一次。 像这样:

function updateTimer(){
    //db->query
    io.sockets.emit('updated data', data);
}
setInterval(updateTimer, 1000);

经过一段时间后,服务器才会停止发送数据。我也在网站上聊天,它也停止了。但是在服务器控制台中没有显示任何内容,没有错误或任何输出,只是"在端口3000上监听..."一直呆在屏幕上。

我认为它可能是循环,但我认为没有其他方法每1秒刷新数据,我是对的吗? 如果有人可以帮助我并需要完整的代码,请打开讨论,我会将其粘贴到某处。

编辑功能代码:

function checkRoulleteTime() {
            try {
                pool.getConnection(function(err, connection) {
                    connection.query('SELECT * FROM `roullete` WHERE status=\'active\'', function(err, rows) {
                        if (err) {
                            console.log(err);
                            return;
                        }
                        if (rows.length == 0) return;
                        var time = rows[0].time - (Math.floor(Date.now() / 1000));
                        if (time <= 1) {
                            connection.query('UPDATE `roullete` SET `status`=\'closed\' WHERE `id`=\'' + rows[0].id + '\'', function(error, fields) {
                                if (error) throw error;
                            });
                            setTimeout(roll, 1000);
                            setTimeout(function(){
                                io.sockets.emit('add hist');
                            }, 10500);
                            setTimeout(updatePoints, 12000);
                            setTimeout(newRound, 12500);
                        }
                        var contagem = Object.keys(clients).length;

                        io.sockets.emit('login count', contagem);
                        io.sockets.emit('roullete time', time);
                        connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'black\'',function(error2, rows2){
                            if (error2) throw error2;
                            connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'green\'',function(error4, rows4){
                                if (error4) throw error4;
                                connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'red\'',function(error3, rows3){
                                    if (error3) throw error3;
                                    var onBlack = rows2[0].points;
                                    var onRed = rows3[0].points;
                                    var onGreen = rows4[0].points;
                                    io.sockets.emit('calculations', {"time": time, "black" : onBlack, "red" : onRed, "green" : onGreen});
                                });
                            });
                        });
                    });

                    connection.release();
                });
            } catch(e) {
                console.log('error here:'+e);
            }
            setTimeout(checkRoulleteTime, 1000);
        }
        setTimeout(checkRoulleteTime, 1000);

好吧,这是我的代码。

1 个答案:

答案 0 :(得分:1)

我的猜测是你的数据库查询中有一些编程错误,在一段时间后耗尽了一些资源,所以你的数据库查询每次都会失败,抛出一个异常或者只是返回一个错误,因此你就不会因为错误而发送任何数据。因为代码在setInterval()回调中,所以不会记录任何异常。

如果您包含实际的数据库代码,我们可能会帮助您进一步帮助您,但您可以通过在其周围放置一个异常处理程序来开始自己调试它:

function updateTimer(){
    try {
        //db->query
        io.sockets.emit('updated data', data);
    } catch(e) {
        console.log(e);
    }
}
setInterval(updateTimer, 1000);

并且,如果您的数据库查询是异步的(我假设它是),则需要在每个回调级别进行显式错误处理和异常(因为异常不会传播异步回调)。

如果您的数据库可能变慢,那么更改您的定期代码可能会更安全:

function updateTimer(){
    try {
        //db->query
        io.sockets.emit('updated data', data);
    } catch(e) {
        console.log(e);
    }
    // schedule next updateTimer() call when this one has finished
    setTimeout(updateTimer, 1000);

}
// schedule first updateTimer() call
setTimeout(updateTimer, 1000);

您的代码中有很多地方泄漏池化连接以及许多您没有记录错误的地方。我的猜测是你用完了连接,一遍又一遍地得到一个你没有记录的错误。

这是您的代码版本,它会尝试清理所有错误,以便记录所有错误并且不会泄漏池化连接。就个人而言,我会使用promises编写此代码,这使得强大的错误处理和报告更容易。但是,这是您的代码的修改版本:

function checkRoulleteTime() {
    try {
        pool.getConnection(function (err, connection) {
            if (err) {
                console.log("Failed on pool.getConnection()", err);
                return;
            }
            connection.query('SELECT * FROM `roullete` WHERE status=\'active\'', function (err, rows) {
                if (err) {
                    connection.release();
                    console.log(err);
                    return;
                }
                if (rows.length == 0) {
                    connection.release();
                    return;
                }
                var time = rows[0].time - (Math.floor(Date.now() / 1000));
                if (time <= 1) {
                    connection.query('UPDATE `roullete` SET `status`=\'closed\' WHERE `id`=\'' + rows[0].id + '\'', function (error, fields) {
                        if (error) {
                            console.log(error);
                            connection.release();
                            return;
                        }
                    });
                    setTimeout(roll, 1000);
                    setTimeout(function () {
                        io.sockets.emit('add hist');
                    }, 10500);
                    setTimeout(updatePoints, 12000);
                    setTimeout(newRound, 12500);
                }
                var contagem = Object.keys(clients).length;
                io.sockets.emit('login count', contagem);
                io.sockets.emit('roullete time', time);
                connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'black\'', function (error2, rows2) {
                    if (error2) {
                        console.log(error2);
                        connection.release();
                        return;
                    }
                    connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'green\', function (error4, rows4) {
                        if (error4) {
                            console.log(error4);
                            connection.release();
                            return;
                        }
                        connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'red\'', function (error3, rows3) {
                            connection.release();
                            if (error3) {
                                console.log(error3);
                                return;
                            }
                            var onBlack = rows2[0].points;
                            var onRed = rows3[0].points;
                            var onGreen = rows4[0].points;
                            io.sockets.emit('calculations', {
                                "time": time,
                                "black": onBlack,
                                "red": onRed,
                                "green": onGreen
                            });
                        });
                    });
                });
            });
        });
    } catch (e) {
        console.log('error here:' + e);
    }
    setTimeout(checkRoulleteTime, 1000);
}
setTimeout(checkRoulleteTime, 1000);

并且为了让您了解对顺序或依赖异步函数进行错误处理和链接的简单程度,这里使用promises重写您的函数。我不知道这是否运行没有错误,因为我无法测试它,但它应该让你知道使用promises编程的清晰度是多少:

var Promise = require('bluebird');
pool = Promise.promisifyAll(pool);

function logErr(err) {
    console.log(err);
}

function checkRoulleteTime() {
    pool.getConnectionAsync().then(function(connection) {
        var query = Promise.promisify(connection.query, {context: connection});
        return query('SELECT * FROM `roullete` WHERE status=\'active\'').then(function(rows) {
            if (rows.length !== 0) {
                var time = rows[0].time - (Math.floor(Date.now() / 1000));
                if (time <= 1) {
                    query('UPDATE `roullete` SET `status`=\'closed\' WHERE `id`=\'' + rows[0].id + '\'').catch(logErr);
                    setTimeout(roll, 1000);
                    setTimeout(function () {
                        io.sockets.emit('add hist');
                    }, 10500);
                    setTimeout(updatePoints, 12000);
                    setTimeout(newRound, 12500);
                }
                var contagem = Object.keys(clients).length;
                io.sockets.emit('login count', contagem);
                io.sockets.emit('roullete time', time);
                function doQuery(color) {
                    return query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'' + color + '\'');
                }
                return Promise.all([doQuery('black'), doQuery('green'), doQuery('red')]).then(function(results) {
                    io.sockets.emit('calculations', {
                        "time": time,
                        "black": results[0][0].points,
                        "green": results[1][0].points,
                        "red": results[2][0].points
                    });
                });

            }
        }).catch(logErr).finally(function() {
            connection.release();
            setTimeout(checkRoulleteTime, 1000);
        });

    }, function(err) {
        console.log("Err getting connection: ", err);
    });
}