NodeJS CouchDB长轮询崩溃

时间:2013-12-24 18:57:51

标签: node.js express couchdb long-polling

当然,我有一个通过ExpressJS在NodeJS上发布的网络应用程序。它使用CouchDB作为它的数据源。我实施了长轮询,以确保所有用户之间的应用始终保持同步。为此,我使用以下逻辑:

  1. 用户登录应用程序,并通过Express路径向Node发出初始长轮询请求。
  2. 节点反过来向CouchDB发出长轮询请求。
  3. 当Couch更新时,它会响应来自Node的请求。
  4. 最后,Node会响应浏览器。
  5. 简单。然而,正在发生的事情是,当我刷新浏览器时,它会冻结每五次刷新。咦?非常奇怪。但我可以一遍又一遍地重现它,即使在我的测试环境中也是如此。每隔五次刷新就会冻结Node并导致应用程序冻结。重新启动节点可以解决问题。

    经过大量的头发拉动我 THOUGHT 我通过更改它来解决它:

    app.get('/_changes/:since*', security, routes.changes);
    

    对此:

    app.get('/_changes/:since*', security, function () { routes.changes });
    

    然而,在进一步测试之后,这只是无法运行routes.changes。所以没有实际解决方案任何想法为什么长期轮询来自Node的CouchDb会做出如此奇怪的事情?在第五次刷新时,我可以在我的路由代码的第一行的节点中有一个断点,它永远不会被击中。但是,在浏览器中我可以打破对节点进行长轮询的请求,它似乎会消失。这就像Node因某种原因不接受连接......

    我是否应该以不同的方式接近从Node到CouchDB的长轮询?我正在使用feed = longpoll,我应该做feed =连续吗?如果我将couchdb中的changes_timeout调低到5秒,它就不会解决问题,但它确实更容易应对,因为冻结仅持续5秒钟。所以这似乎表明节点无法处理几个未完成的请求。也许我会尝试连续喂食,看看会发生什么。

    self.getChanges = function(since){

    浏览器:

            $.ajax({
                url: "/_changes/" + since,
                type: "GET", dataType: "json", cache: false,
                success: function (data) {
                    try {
                        self.processChanges(data.results);
                        self.lastSeq(data.last_seq);
                        self.getChanges(self.lastSeq());
                        self.longPollErrorCount(0);
                    } catch (e) {
                        self.longPollErrorCount(self.longPollErrorCount() + 1);
    
                        if (self.longPollErrorCount() < 10) {
                            setTimeout(function () {
                                self.getChanges(self.lastSeq());
                            }, 3000);
                        } else {
                            alert("You have lost contact with the server. Please refresh your browser.");
                        }
                    }
    
                },
                error: function (data) {
                    self.longPollErrorCount(self.longPollErrorCount() + 1);
    
                    if (self.longPollErrorCount() < 10) {
                        setTimeout(function () {
                            self.getChanges(self.lastSeq());
                        }, 3000);
                    } else {
                        alert("You have lost contact with the server. Please refresh your browser.");
                    }
                }
            });
        }
    

    节点:

    路由:

    exports.changes = function (req, res) {
    
        var args = {};
        args.since = req.params.since;
    
        db.changes(args, function (err, body, headers) {
    
            if (err) {
                console.log("Error retrieving changes feed: "+err);
                res.send(err.status_code);
            } else {
    
                //send my response... code removed here
            }
        })
    }
    

    数据库长轮询调用:

    self.changes = function (args, callback) {
    
        console.log("changes");
    
        if (args.since == 0) {
            request(self.url + '/work_orders/_changes?descending=true&limit=1', function (err, res, headers) {
                var body = JSON.parse(res.body);
                var since = body.last_seq;
                console.log("Since change: "+since);
                self.longPoll(since, callback);
            });
        } else {
            self.longPoll(args.since, callback);
        }
    }
    
    self.longPoll = function (since, callback) {
    
        console.log("about to request with: "+since);
    
        request(self.url + '/work_orders/_changes?feed=continuous&include_docs=true&since=' + since,
        function (err, res, headers) {
    
            console.log("finished request.")
    
            if (err) { console.log("Error starting long poll: "+err.reason); return; } //if err send it back
    
            callback(err, res.body);
        });
    }
    

1 个答案:

答案 0 :(得分:0)

Socket.io将自动回退到长轮询,并且没有像您所拥有的那样的问题。所以就这样使用它。另外,对于CouchDB更改,请使用此https://github.com/iriscouch/follow或者像其他人建议的那样https://npmjs.org/package/changes

当我们拥有已经满足你需要的流行模块时,重新发明的东西是非常糟糕的做法。目前https://npmjs.org/上有超过52,000个节点模块。人们在复制和粘贴代码方面做了大量工作。在我看来,重塑基本的东西比这更糟糕。

我知道有很多模块很难知道所有这些模块,所以我并不是说你永远无法解决与其他人相同的问题。但首先看看npmjs.org以及http://node-modules.com/之类的网站,它们可能会提供更好的搜索结果。