如何设置RedisStore - Node,Express,Socket.io,Heroku

时间:2014-06-30 21:34:44

标签: node.js heroku express socket.io

我正在使用Node&在Heroku上部署了Express 4.0,我试图用Redis实现Socket.io作为会话存储。所以我将此作为我当前的代码:

 var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var RedisStore = io.RedisStore;

if (process.env.REDISTOGO_URL) {
    // inside if statement
    var rtg   = require("url").parse(process.env.REDISTOGO_URL);
    var redis = require("redis").createClient(rtg.port, rtg.hostname);

    redis.auth(rtg.auth.split(":")[1]);
} else {
    var redis = require("redis").createClient();
}

/** Initialize RedisStore for socket.io **/
io.set('store', new RedisStore({
  redis    : redis
}));

但是我收到以下错误:

14:25:03 web.1  | io.set('store', new RedisStore({
14:25:03 web.1  |                 ^
14:25:03 web.1  | TypeError: undefined is not a function

我也看到了这种定义RedisStore的方式:

var redis = require('socket.io/node_modules/redis');
var RedisStore = require('socket.io/lib/stores/redis');

但是,我安装的使用npm install --save socket.io安装的socket.io版本并未在stores目录中包含lib

enter image description here


修改

我在socket.io页面上看到了关于1.0版本的内容:

// 2. Implement the socket.io-redis adapter

var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));

但是我没有找到关于这个新模块的其他文档,而且由于我是这个新版本的新手,我不认为我可以自己解决这个问题。 / p>

4 个答案:

答案 0 :(得分:7)

node.js模块之间的趋势是删除不是模块真正核心的功能。

这就是为什么socket.io 1.0不再支持redis开箱即用。

因此,第一步是追踪您需要的功能。

  1. http://socket.io/docs/server-api/
  2. https://github.com/Automattic/socket.io-adapter
  3. https://github.com/Automattic/socket.io-redis
  4. 然后您需要安装另一个模块npm install socket.io-redis --save

    最后配置您的应用。

    var app = express();
    var server = require('http').createServer(app);
    var io = require('socket.io').listen(server);
    var redis = require('socket.io-redis');
    
    io.adapter(redis(process.env.REDISTOGO_URL));
    

    好的部分是socket.io-redis适配器接受redis网址并默认为localhost:6379所以你(应该)能够简单地传递REDISTOGO_URL

答案 1 :(得分:5)

我必须解析上面的库以获得这个例子,所以我想我会发布一个完整的例子,但我必须承认有一些关闭,这使用REDISCLOUD,它在Heroku上,它确实有效。我会把它发布在其他地方,也可能把它放在一个文档中。

var redis = require('redis');
var ioredis = require('socket.io-redis'); //Adapter
var url = require('url'); 
var redisURL = url.parse(process.env.REDISCLOUD_URL );

var pub = redis.createClient(redisURL.port, redisURL.hostname, {return_buffers: true});
var sub = redis.createClient(redisURL.port, redisURL.hostname, {return_buffers: true});
pub.auth(redisURL.auth.split(":")[1]);
sub.auth(redisURL.auth.split(":")[1]);

var redisOptions = {
  pubClient: pub,
  subClient: sub,
  host: redisURL.hostname,
  port: redisURL.port
};

io.adapter(ioredis(redisOptions));

答案 2 :(得分:1)

以下代码适用于Heroku Redis,希望这会有所帮助。

var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);

var redis = require('redis');
var redisAdapter = require('socket.io-redis');

io.adapter(redisAdapter({
    pubClient: redis.createClient(process.env.REDIS_URL, {return_buffers: true}),
    subClient: redis.createClient(process.env.REDIS_URL, {return_buffers: true})
}));

答案 3 :(得分:0)

对于感兴趣的人, 这是我在最新的socket.io上运行的原型聊天服务器,带有express,多核和redis作为中间件。 无论是否连接到不同的节点和端口实例,广播的消息都会发送给所有房间用户。 跑吧

  • node server.js

和其他机器

  • node client.js
  • 或用于测试节点client.js 7001,7002,7003 ......

server.js

  var options = {
    //workers: 2, // total workers (default: cpu cores count).
    first_port: 7000, // 8000, 8001 are worker's ports (default: 8000).
    proxy_port: 5000, // default (5000).
    session_hash: function (req, res) { return req.connection.remoteAddress; },
    no_sockets: false // allow socket.io proxy (default: false).
    };

require('sticky-socket-cluster')(options, start);

function start(port) {
    // requirements
    var express = require('express');
    var http = require('http');
    var socketio = require('socket.io');
    var path = require('path');
    var sticky = require('sticky-session');

    var app = express();

    var server = http.createServer(app);
    var io = socketio.listen(server);

    var redis = require('socket.io-redis');
    io.adapter(redis({ host: 'localhost', port: 6379 }));

    server.listen(port, function() {
      console.log(' - listening on ' + port+ ' ' + __dirname);
    });

    // require our chatserver
    var ChatServer = require('./chatserver');

    // initialize a new chat server.
    new ChatServer({io: io, port: port}).init();
}

chatserver.js

RoomUtil = (function(){

    roomMessages = {};

    return {

        getMessages : function(room_id,limit,cb){
            //TODO
            cb(roomMessages[room_id] || []);
        },

        postMessage : function(message,room_id,cb){

            if (!roomMessages[room_id]) roomMessages[room_id] = [];
            roomMessages[room_id].push(message);
            cb();
        }
    }   
})();

var Server = function(options) {
  var self = this;

  self.io = options.io;

  // users array
  self.users = [];

  // initialize function
  self.init = function() {
      console.log("init");
    // Fired upon a connection
    self.io.on('connection', function(socket) {
      console.log("incoming connection");
     // var ru = new RoomUser();
      self.handleConnection(socket,options.port);
    });
  }

  // socket handler for an incoming socket
  self.handleConnection = function(socket,port) {
    // wait for a login message

    socket.emit("incoming connection",{}); 

    socket.on("joinroom",function(data,joinroom_callback){

        console.log("attempt to join room ",data.room_id," on port ",port);
        if (!data.room_id){
            console.log("cannon join room -> no room id given");
            return socket.disconnect();
        }
        else{

            var room_id = data.room_id;

            socket.join(room_id,function(){

                console.log(socket.rooms);

                RoomUtil.getMessages(data.room_id,50,function(messages){
                    console.log("client succesfully joined room ",data.room_id);
                    joinroom_callback(null,{'messages':messages});
                });

                socket.on("login",function(data,login_callback){

                    if (!data.username){
                        login_callback("invalid userdata",null);        
                    }
                    else{

                        login_callback(null,1);

                        socket.on("post_message",function(data,message_callback){

                            if (!data.message || data.message == ""){
                                console.log("empty message posted. ignore");
                                message_callback("invalid_message",null);
                            }
                            else{
                                console.log("received message on port ",port,data.message);
                                message_callback(null,1);
                                RoomUtil.postMessage(data.message,room_id,function(){
                                    RoomUtil.getMessages(room_id,50,function(messages){
                                        console.log("emit messages to room id ",room_id);
                                        //socket.to(room_id).emit('update_messages', messages);
                                        //socket.broadcast.to(room_id).emit('update_messages', messages);
                                        //socket.broadcast.to(room_id).emit('update_messages', messages);
                                        //self.io.to(room_id).emit('update_messages', messages);
                                        self.io.in(room_id).emit('update_messages', messages);
                                    });
                                })
                            }
                        });
                    }       
                });
            });
        }
    });
  }
}

module.exports = Server;

client.js

var servercon = 'http://localhost:'+(process.argv[2] || 5000);

console.log("going to connect to "+servercon)
var socket = require('socket.io-client')(servercon); 

var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

socket.on('connect', function(){
    console.log("connected, going to login");

    socket.emit("joinroom",{"room_id":123123}, function(error,data){

        if (error){
            console.log("cannot join room ",error);
        }
        else{
            console.log("succesfully joined room -> going to login now");

            console.log("received messages count",data.messages.length);

            socket.emit("login",{username:"John Mckain"}, function(error, message){

                if (error){
                    console.log("error logging in ",error);
                }
                else{
                    console.log("logged in succesfully -> post message now");

                    var readline = function(){
                        rl.question("type in a message -> ", function(message) {

                            socket.emit("post_message",{'message':message}, function(error, message){

                                if (error){
                                    console.log("error posting message");
                                    readline();
                                }
                                else{
                                    console.log("succesfully posted message");
                                    readline();
                                }

                            });
                        });
                    }
                    readline();
                }

            });

            socket.on("update_messages",function(data){
                console.log("received new messages count ",data.length,data);
            });
        }
    });
});
socket.on('event', function(data){
    console.log("event send",data);
});
socket.on('disconnect', function(e){
    console.log("disconnected",e);
});

socket.on("welcome",function(data){
    console.log("on welcome ",data)
})

socket.on("pong",function(e){
    console.log("pong")
})