在Heroku上运行显示的代码片段我看到程序行为的主要区别取决于我是使用我的redis服务器还是heroku redis附加组件(尝试使用RedisCloud和RedisToGo失败)。 / p>
测试代码是通过primus房间的websis发射器的Redis PubSub。
我将首先展示预期的计划行为。
我有REDISLOCAL_URL环境变量指向我自己的redis服务器,运行redis 2.8.6(与RedisCloud版本相同)
在日志中我看到:
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":30,"msg":"Server running on port 19690","time":"2014-04-27T16:38:38.706Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Redis Sub ready on ckir.homeip.net","time":"2014-04-27T16:38:39.226Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Redis Pub ready on ckir.homeip.net","time":"2014-04-27T16:38:39.225Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Redis Pub authenticated","time":"2014-04-27T16:38:39.224Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Redis Sub authenticated","time":"2014-04-27T16:38:39.226Z","v":0}
此时我连接了一个客户端(外部浏览器)。一切都很好,我可以在浏览器上看到时间。
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client connected id: 1398617743234$0","time":"2014-04-27T16:55:43.236Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client subscribed to time, 1 total subscriptions","time":"2014-04-27T16:55:43.595Z","v":0}
此时我按下浏览器上的重新加载。正如预期的那样,程序断开连接并取消订阅,然后重新连接并再次订阅。无论我按重载多少次,行为都保持不变。
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client disconnected id: 1398617743234$0","time":"2014-04-27T16:56:06.995Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client unsubscribed from time, 0 total subscriptions","time":"2014-04-27T16:56:07.160Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client connected id: 1398617768295$1","time":"2014-04-27T16:56:08.298Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client subscribed to time, 1 total subscriptions","time":"2014-04-27T16:56:08.630Z","v":0}
此时我关闭了浏览器,因此没有重新连接。
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client disconnected id: 1398617768295$1","time":"2014-04-27T16:56:31.229Z","v":0}
{"name":"index","hostname":"04580326-9e33-4829-bf89-301e10f85fe7","pid":2,"level":20,"msg":"Client unsubscribed from time, 0 total subscriptions","time":"2014-04-27T16:56:31.393Z","v":0}
此时我输入" heroku配置未设置REDISLOCAL_URL"所以heroku重启了dyno,我明白了。
Redis connections closed
这次我将使用RedisCloud重复上述步骤。
我们开始很好。连接很好。
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":30,"msg":"Server running on port 35323","time":"2014-04-27T16:57:17.215Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Redis Sub ready on pub-redis-10891.us-east-1-2.1.ec2.garantiadata.com","time":"2014-04-27T16:57:17.242Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Redis Pub ready on pub-redis-10891.us-east-1-2.1.ec2.garantiadata.com","time":"2014-04-27T16:57:17.243Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Redis Sub authenticated","time":"2014-04-27T16:57:17.237Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Redis Pub authenticated","time":"2014-04-27T16:57:17.242Z","v":0}
此时我连接了一个客户端(外部浏览器)。一切都很好,我可以在浏览器上看到时间。
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Client connected id: 1398617858982$0","time":"2014-04-27T16:57:38.985Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Client subscribed to time, 1 total subscriptions","time":"2014-04-27T16:57:39.150Z","v":0}
我在浏览器上按重新加载,这就是问题所在。不再需要重新连接和重新订阅,也没有更多数据进入浏览器屏幕。
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Client disconnected id: 1398617858982$0","time":"2014-04-27T16:57:58.560Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Client unsubscribed from time, 0 total subscriptions","time":"2014-04-27T16:57:58.561Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Client connected id: 1398617879988$1","time":"2014-04-27T16:57:59.989Z","v":0}
{"name":"index","hostname":"97617fd4-4224-4c3f-a638-3b9f6840fdb7","pid":2,"level":20,"msg":"Client disconnected id: 1398617879988$1","time":"2014-04-27T16:58:13.798Z","v":0}
我需要重新启动dyno以使浏览器客户端再次运行。任何想法为什么会这样?任何可能的解决方法?
Bellow是我和package.json文件一起使用的代码,用于更好的文档。
'use strict';
//
// Program exit handlers to close redis connections
//
var Sync = require('sync');
process.stdin.resume(); //so the program will not close instantly
function connectionsclose() {
redisPub.end();
redisSub.end();
console.log("Redis connections closed");
process.exit();
}
function exitHandler(options, err) {
if (options.cleanup) {
Sync(function() {
connectionsclose();
});
}
if (err) {
Sync(function() {
connectionsclose();
});
}
if (options.exit) {
process.exit();
};
}
//do something when app is closing
process.on('exit', exitHandler.bind(null, {
exit: true
}));
//catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, {
cleanup: true
}));
process.on('SIGTERM', exitHandler.bind(null, {
cleanup: true
}));
//catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null, {
cleanup: true
}));
//
// Start logging
//
var path = require('path');
var bunyan = require('bunyan');
var port = process.env.PORT || 3000;
var basename = path.basename(__filename, '.js');
var log = bunyan.createLogger({
name: basename,
streams: [{
level: 'debug',
stream: process.stdout
}, {
level: 'info',
path: path.resolve('./logs/' + basename + '.log'),
}]
});
//
// Do your express magic.
//
var express = require('express');
var app = express();
app.set('port', port);
app.use(express.static(__dirname + '/public'));
app.get('/keepalive', function(req, res) {
res.send('OK');
});
//
// Create Primus server
//
var http = require('http');
var Primus = require('primus');
var server = http.createServer(app);
var primus = new Primus(server, {
transformer: 'websockets',
parser: 'JSON',
});
primus.save(__dirname + '/public/primus.js');
primus.on('connection', function(spark) {
log.debug("Client connected id: " + spark.id);
spark.on('data', function(data) {
data = data || {};
log.trace("Client id: " + spark.id + " message: " + JSON.stringify(data));
switch (data.command) {
case 'join':
redisSub.subscribe(data.room);
break;
case 'leave':
redisSub.unsubscribe(data.room);
break;
default:
log.debug("Client " + spark.id + " wrote " + JSON.stringify(message));
}
});
});
primus.on('disconnection', function(spark) {
log.debug("Client disconnected id: " + spark.id);
// unsubscribe from all the previously subscribed channels
redisSub.unsubscribe();
});
server.listen(app.get('port'), function() {
log.info('Server running on port ' + app.get('port'));
});
//
// Connect to redis server
//
//For localhost password at /etc/redis/redis.conf at requirepass
var redis = require('redis');
//redis.debug_mode = true;
var url = require('url');
if (typeof process.env.REDISLOCAL_URL !== "undefined") {
var redisURL = url.parse(process.env.REDISLOCAL_URL);
} else {
var redisURL = url.parse(process.env.REDISCLOUD_URL);
}
var redisPub = redis.createClient(redisURL.port, redisURL.hostname, {
no_ready_check: true
});
redisPub.auth(redisURL.auth.split(":")[1], function() {
log.debug("Redis Pub authenticated");
});
redisPub.on("ready", function(err) {
log.debug("Redis Pub ready on " + redisURL.hostname);
});
redisPub.on("error", function(err) {
log.error("Redis Error " + err);
});
redisPub.on("end", function() {
log.error("Redis Pub connection closed ");
});
var redisSub = redis.createClient(redisURL.port, redisURL.hostname, {
no_ready_check: true
});
redisSub.auth(redisURL.auth.split(":")[1], function() {
log.debug("Redis Sub authenticated");
});
redisSub.on("ready", function() {
log.debug("Redis Sub ready on " + redisURL.hostname);
});
redisSub.on("error", function(err) {
log.error("Redis Error " + err);
});
redisSub.on("subscribe", function(channel, count) {
log.debug("Client subscribed to " + channel + ", " + count + " total subscriptions");
});
redisSub.on("unsubscribe", function(channel, count) {
log.debug("Client unsubscribed from " + channel + ", " + count + " total subscriptions");
});
redisSub.on("message", function(channel, message) {
log.trace("Client channel " + channel + ": " + message);
primus.write({
room: channel,
msg: message
});
});
redisSub.on("end", function() {
log.error("Redis Sub connection closed ");
});
// A time channel for debugging
setInterval(function() {
redisPub.publish('time', new Date().toISOString(), function() {});
}, 5000);
这是package.json
{
"name": "rtnetsrvredis",
"version": "0.0.1",
"description": "Connect a Redis PubSub channel to a primus room",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "CK",
"license": "MIT",
"dependencies": {
"bunyan": "^0.22.3",
"express": "^4.1.0",
"hiredis": "^0.1.16",
"primus": "^2.2.0",
"redis": "^0.10.1",
"sync": "^0.2.2",
"ws": "^0.4.31"
}
}