#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
Я протестировал его следующими шагами:
- узел server.js
- ./client.sh
- В 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;
});
}