【问题标题】:NodeJS CouchDB Long Polling DebacleNodeJS CouchDB 长轮询崩溃
【发布时间】:2013-12-24 18:57:51
【问题描述】:

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

  1. 用户登录应用并通过 Express 路由向 Node 发出初始长轮询请求。
  2. 节点依次向 CouchDB 发出长轮询请求。
  3. 当 Couch 更新时,它会响应来自 Node 的请求。
  4. Node 最后响应浏览器。

简单。但是,正在发生的事情是,当我刷新浏览器时,它会在每五次刷新 时冻结。嗯?很奇怪。但我可以一遍又一遍地重现它,即使在我的测试环境中也是如此。每第五次刷新都会冻结 Node 并导致应用程序冻结。重启节点解决了这个问题。

在拉了很多头发之后,我想到我通过改变这个来解决它:

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=continuous?如果我将 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);
    });
}

【问题讨论】:

  • node 绝对可以处理很多到 couchdb 的连接。你能分享如何处理连接的代码吗?
  • 已更新代码。我想知道是否需要将我的请求推送到一个数组中并跟踪它们?那么当新的请求以某种方式出现时,只是将它们放在以前提出的请求上?还是取消旧请求并创建新请求?
  • 我看不出请求端有什么问题。您不需要跟踪所有长轮询请求。我怀疑冻结来自一些你无法摆脱的沉重循环,所以也许尝试在你的回调中搜索那些
  • 我认为使用请求库创建一个长轮询到沙发是在某种程度上造成了问题。首先我正在轮询节点,然后节点对 Couchdb 运行长轮询。但是当我更改我的代码以便 Node 不会长时间轮询沙发,而是每 5 秒短轮询一次,并且当有更改时发送响应时,它就可以工作了。
  • 我想我可能会尝试切换到这个库以备将来使用:

标签: node.js express couchdb long-polling


【解决方案1】:

Socket.io 将自动退回到长轮询,并且不会像您遇到的那样出现问题。所以就用那个。对于 CouchDB 的更改,也可以使用这个 https://github.com/iriscouch/follow 或者这个 https://npmjs.org/package/changes,就像其他人建议的那样。

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

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

【讨论】:

  • 是的,我将尝试上面的库之一,正如我在问题上的 cmets 中所述。当涉及到长轮询时,我什至没有想过要寻找特定于 couchdb 更改的库。老实说,有时我喜欢尽可能简单地实现事物,只是为了了解它是如何工作的。但最后我同意,重新发明任何东西都没有意义。我会试试这些。
猜你喜欢
  • 2016-03-30
  • 1970-01-01
  • 2019-03-25
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 2013-08-08
  • 2011-08-08
  • 1970-01-01
相关资源
最近更新 更多