2016-09-27 84 views
8

我正在使用redis作为pubsub messenger在python和node之间建立实时可视化。有一个总是运行的python脚本,它用hmset设置redis hash。如果我在Redis客户端中输入以下示例命令:“HGETALL'sellers-80183917'”,那么该应用程序的这一方工作正常,我最终得到正确的数据。无法接收来自套接字io的redis数据

问题出在js方面。我使用socketio和redis nodejs库来监听redis实例并通过d3js viz在线发布结果。

我运行下面的代码节点:

var express = require('express'); 
var app = express(); 
var redis = require('redis'); 

app.use(express.static(__dirname + '/public')); 


var http = require('http').Server(app); 


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



redisSubscriber = redis.createClient(6379, 'localhost', {}); 


redisSubscriber.on('message', function(channel, message) { 
    io.emit(channel, message); 
}); 



app.get('/sellers/:seller_id', function(req, res){ 
    var seller_id = req.params.seller_id; 
    redisSubscriber.subscribe('sellers-'.concat(seller_id)); 


    res.render('seller.ejs', { seller:seller_id }); 
}); 


http.listen(3000, '127.0.0.1', function(){ 
    console.log('listening on *:3000'); 
}); 

这是正在接受用户请求和输出即在seller.ejs文件的相关部分:

 var socket = io('http://localhost:3000'); 
     var stats; 
     var seller_key = 'sellers-'.concat(<%= seller %>); 
     socket.on(seller_key, function(msg){ 
      stats = []; 
      console.log('Im in'); 
      var seller = $.parseJSON(msg); 
      var items = seller['items']; 
      for(item in items) { 
       var item_data = items[item]; 
       stats.push({'title': item_data['title'], 'today_visits': item_data['today_visits'], 'sold_today': item_data['sold_today'], 'conversion_rate': item_data['conversion_rate']}); 
      } 
      setupData(stats); 
     }); 

问题是因为socket_on()方法从来没有收到任何东西,我也没有看到问题出在哪里,因为除此之外,一切看起来都很好。

回答

1

我认为你可能会对Redis中的Pub/Sub实际上是什么感到困惑。它是而不是一种聆听哈希变化的方法;您可以通过发布/订阅频道调用sellers-1,并且您可以使用散列和密钥sellers-1,但这些密钥彼此不相关。

如记录here

的Pub/Sub没有任何关系的关键空间。

有一件东西叫做keyspace notifications,可以用来听取关键空间(通过Pub/Sub通道)的变化;但是,此功能默认情况下未启用,因为它会占用更多资源。

也许更简单的方法是在HMSET之后发布消息,因此任何订阅者都知道散列已经发生变化(他们会自己检索散列内容,或者发布的邮件将包含相关数据)。

这给我们带来了下一个可能的问题:您只有一个用户连接,redisSubscriber

从我对Node.js Redis驱动程序的理解中,在这样的连接上调用.subscribe()将删除任何以前的订阅,以支持新订阅。因此,如果您之前订阅了sellers-1频道并订阅了sellers-2,您将不会再收到sellers-1频道的消息。

您可以通过多渠道听取传递通道的阵列,或将它们作为一个参数:

redisSubscriber.subscribe([ 'sellers-1', 'sellers-2', ... ]) 
// Or: 
redisSubscriber.subscribe('sellers-1', 'sellers-2', ...) 

你很明显会跟踪每个“活动”卖家订阅。要么是这样,要么为每个订阅创建一个新的连接,这也是不理想的。

有一个发布所有更改的发布/订阅渠道可能是一个更好的主意,而不是每个销售者的单独渠道。

最后:如果你的卖家ID不难猜测(例如,如果它是基于增量整数值的话),对于有人编写一个客户端来说,这将是微不足道的,卖家频道他们想要。这可能不是问题,但需要注意的事情。