Node + Redis + PHP获得实时问题

时间:2014-10-13 22:54:34

标签: node.js sockets redis socket.io node-redis

我在NodeJS + Redis + PHP中构建一个发布/订阅服务器,在深入研究主题并开始构建某些东西之后,我遇到了一些我在这个过程中看到的混乱。

示例场景:

  • 5 用户通过NodeJs正确连接到套接字。
  • 其中一个点击按钮向自己以外的所有已关联用户发送自定义alert
  • Php通过调用ajax(为了举例)接收警报消息
  • Php发布回Redis
  • Redis收到事件并触发socket.io来广播事件

设置视图:

<input type="text" id="message">
<button id="sendMessage">Send alert</button>

客户端Js

var socket = io.connect('http://127.0.0.1:3000/');

socket.on('notification', function (data) {

    alert(data.message);
    console.log('message received');
});

// Ajax event
$(document).on('click','#sendMessage', function(){

    $.ajax({
      url: '/send/notification',
      method: 'POST',
      type: 'JSON',
      data: { message: $('#message').val() },
      success:function(data)
      {
        console.log('message sent');
      }
    })
});

用于与redis通信的Php服务器端

$message = $_POST['message'];
$redis = new Predis\Client();
$redis->publish('notification',$message);

的NodeJS

此时我的NodeJs服务器上的我将在redis中收听消息事件,然后将事件广播到套接字,但这是我遇到的第一个问题。

var http = require('http');
var app  = http.createServer();
var io   = require('socket.io')(app);
var redis = require('redis');

app.listen(3000,'127.0.0.1',function(){
    console.log("listening:", app.address().port, app.address().address);
});

io.on('connection', function(client){
    var redisClient = redis.createClient();

    redisClient.subscribe('notification');

    redisClient.on("message",function(channel,data){

          // This line should broadcast to all the client except the sender
          socket.broadcast.emit(channel,JSON.parse(data));

          console.log(channel);
    });
});

问题

此时我console.log()我可以在我的终端5日志上看到channel&#34;通知&#34;为什么5?

当socket.io broadcast事件时,它执行 5次,在这种情况下发送 5 alert()到{{1并且 4 clients而不是1为所有客户端为0为发件人。

时间取决于连接的用户数量我真的不明白我错过了什么,因为它不应该是正确的行为。

我已经尝试将sender的创建和redisClient之外的频道订阅设置为没有运气,同样的结果。


另一项测试

如果我io.on('connection')套接字连接上的事件如下:

broadcast

它正常工作,所以我认为是re​​dis问题。任何建议都会非常感激。

2 个答案:

答案 0 :(得分:2)

您连接了5个客户端,因此“连接”事件被触发5次。 因此,有5个redis听众,然后播放。

有两种方法可以正确完成:

a)每个连接1个监听器,仅将消息发送到连接

io.on('connection', function(socket){
    var redisClient = redis.createClient();

    redisClient.subscribe('notification');

    redisClient.on("message",function(channel,data){

          // This line should broadcast to only the current connection
          socket.emit(channel,JSON.parse(data));

          console.log(channel);
    });
});

b)1个全局监听器,向所有客户端广播

var redisClient = redis.createClient();

redisClient.subscribe('notification');

redisClient.on("message",function(channel,data){

   // This line should broadcast to all the client except the sender
   io.sockets.emit(channel,JSON.parse(data));

   console.log(channel);
});

我更喜欢方法b)因为它只需要一个redis连接。

答案 1 :(得分:-1)

我在一个项目中做了同样的事情。唯一不同的是我从node.js发布通知但我没有得到任何问题。有广播只有开放套接字。