Почему я не смог получить первые несколько ответов с HTTPServer NodeJS?

#javascript #http #node.js #comet #redis

#javascript #http #node.js #comet #redis

Вопрос:

Я планирую использовать NodeJS в качестве своего сервера comet и написал некоторый код для тестирования, но есть проблема, из-за которой, когда клиент подключается к серверу в первый раз, он не может получить ответ от сервера.

Вот код на стороне сервера (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. узел server.js
  2. ./client.sh
  3. В redis, LPUSH (‘msg: q: 1’, ‘blablah’)

Теперь «Отправлено: blablah», напечатанное на консоли, res.end(reply) оправдано, но клиент ничего не получает. Я повторяю шаг 3 много раз, затем он работает так, как ожидалось. Если я перезапущу клиент, первые несколько ответов не смогут быть получены снова.

Как я могу это решить?

Комментарии:

1. Попробуйте не использовать бесконечный цикл while, а просто создайте цикл for до 5 или 10. Затем посмотрите, происходит ли это по-прежнему.

2. Raynos: Спасибо. Клиент находится в режиме блокировки, ожидая ответа. если я просто выполню команду ‘curl -i http:// …’, ничего не изменится, по-прежнему не удается получить ответ.

3. похоже, что все повторяется. Для меня код узла выглядит нормально.

4. Попробуйте запустить команду MONITOR в redis-cli , чтобы увидеть, все ли работает так, как ожидалось

Ответ №1:

Я думаю, что здесь может произойти то, что вы прервали curl, пока он ожидал ответа от 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;
    });
}