【问题标题】:Node + Redis + PHP getting RealTime IssueNode + Redis + PHP 得到实时问题
【发布时间】:2014-12-08 14:51:56
【问题描述】:

我正在用 NodeJS + Redis + PHP 构建一个 Pub/Sub 服务器,在深入研究了这个主题并开始构建一些东西之后,我在这个过程中遇到了一些困惑。

示例场景:

  • 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 中侦听 message 事件,然后将事件广播到套接字,但这是我遇到的第一个问题。

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()channel在我的终端上可以看到5个日志“通知”为什么是5个?

当 socket.io broadcast 事件发生时,它会执行 5 次,在这种情况下发送 5 alert()clients 4sender,而不是所有客户端的 1 和发件人的 0。

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

我已经尝试将redisClient 的创建和频道订阅放在io.on('connection') 之外,但没有成功,结果相同。


另一个测试

如果我broadcast 套接字连接上的事件是这样的:

io.on('connection', function(client)
{
     client.broadcast.emit('notification','hello');
});

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

【问题讨论】:

  • 有点离题,但我不太清楚你为什么使用 PHP。您可以只调用 NodeJS WebService 来发布消息,并且您将摆脱开发堆栈的另一部分(除非您不需要 PHP 来处理其他事情)...

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


【解决方案1】:

您有 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 连接。

【讨论】:

  • 非常感谢您的回答,我做了同样的实验。使用方法 b) 它不应该向所有客户端(甚至发送者)发出。如果我改用 broadcast 方法,它会发疯地分别发送 2 个通知。在方法 a) 上,它向所有客户端发出相同的信息,但是您所说的具有多个连接。如何使用方法 b) 和 broadcast 方法将事件发送给除发送者之外的所有客户端?如果你不介意的话,我想和你聊聊,这对我很有用。 chat.stackoverflow.com/rooms/63024/nodejs-redis-php
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2014-07-04
    • 2021-03-13
    • 1970-01-01
    • 2013-06-22
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多