为什么我无法从nodeJS的httpServer获得前几个响应?

时间:2011-04-13 15:19:03

标签: javascript http node.js comet redis

我打算使用nodeJS作为我的彗星服务器,我编写了一些代码用于测试,但是有一个问题是,当客户端第一次连接到服务器时,它无法从服务器获得响应。

这是服务器端代码(server.js):

var util = require('util');
var redis = require('redis').createClient(6379, '192.168.1.254');
var http = require('http');
redis.on("error", function (err) {
    console.log("Error " + err);
});

var server = http.createServer(requestListener);
server.listen(9898, '192.168.1.254');

function requestListener(req, res) {
        util.log('Connected.');
        redis.brpoplpush('msg:q:1', 'msg:s:1', 20, function(err, reply) {
                if (err) {
                        util.log('ERROR: ' + err);
                }
                var length = reply ? reply.length : 0;
                res.writeHead(200, {
                        'Content-Type':'text/plain',
                        'Content-Length':length
                });
                if (length) {
                        res.end(reply);
                        util.log('Sent: ' + reply);
                } else {
                        res.end('');
                }
        });
}

客户端代码(client.sh):

#!/bin/bash
while [ 1 ]
do
        curl -i http://192.168.1.254:9898
done

我按照以下步骤测试了它:

  1. node server.js
  2. ./ client.sh
  3. 在redis中,LPUSH('msg:q:1','blablah')
  4. 现在,“发送:blablah”打印在控制台上,res.end(reply)已经执行,但客户端什么也没收到。我多次重复步骤3,然后按预期工作。如果我重新启动客户端,则无法再接收前几个响应。

    我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我认为这里可能发生的事情是你在等待redis的响应时已经中止了卷曲。中止HTTP客户端后,redis命令仍保持活动状态。然后将另一个元素推送到队列中,redis命令返回,但没有HTTP响应将其写入。当您再次启动curl循环时,您会发现队列为空。

以下是程序的修改版本,它会对响应进行流式处理并检测客户端中止。它不会将元素放回队列中,但你也可以这样做。

var util = require('util');
var redis = require('redis').createClient();
var http = require('http');

redis.on("error", function (err) {
    console.log("Redis error " + err);
});
redis.on("ready", function () {
    console.log("Redis client ready");
});

var server = http.createServer(requestListener);
server.listen(9898);

function requestListener(req, res) {
    var aborted = false;

    res.writeHead(200, {
        "Content-Type": "text/plain"
    });
    res.write("Checking redis...\n");
    redis.brpoplpush('q', 's', 20, function (err, reply) {
        if (aborted) {
            return console.log("Client aborted before redis reply came back.");
        }

        if (err) {
            return res.end("Redis error");
        }

        res.end("Redis reply: " + reply);
    });
    req.on("aborted", function () {
        console.log("HTTP client aborted.");
        aborted = true;
    });
}