Node.js 节点+;Redis+;PHP实时性问题
我正在NodeJS+Redis+PHP中构建一个Pub/Sub服务器,在深入研究这个主题并开始构建一些我在过程中遇到的困惑之后 示例场景:Node.js 节点+;Redis+;PHP实时性问题,node.js,sockets,redis,socket.io,node-redis,Node.js,Sockets,Redis,Socket.io,Node Redis,我正在NodeJS+Redis+PHP中构建一个Pub/Sub服务器,在深入研究这个主题并开始构建一些我在过程中遇到的困惑之后 示例场景: <input type="text" id="message"> <button id="sendMessage">Send alert</button> 5个用户通过NodeJs正确连接到插座 其中一个用户单击按钮向除他以外的所有连接用户发送自定义警报 Php通过调用ajax接收警报消息(示例) Php发布回Redi
<input type="text" id="message">
<button id="sendMessage">Send alert</button>
- 5个用户通过
正确连接到插座李>NodeJs
- 其中一个用户单击按钮向除他以外的所有连接用户发送自定义
警报
- Php通过调用ajax接收警报消息(示例)
- Php发布回Redis
- Redis接收事件并触发socket.io以广播事件
<input type="text" id="message">
<button id="sendMessage">Send alert</button>
用于与redis通信的Php服务器端
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');
}
})
});
$message = $_POST['message'];
$redis = new Predis\Client();
$redis->publish('notification',$message);
NodeJs
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');
}
})
});
$message = $_POST['message'];
$redis = new Predis\Client();
$redis->publish('notification',$message);
此时,在我的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);
});
});
问题
此时,我可以在终端5上看到console.log()
channel日志“notification”Why 5
当socket.io广播该事件时,它会执行5次,在这种情况下,会向客户端发送5警报()
,并向发送方发送4,而不是向所有客户端发送0
时间取决于连接了多少用户,我真的不明白我错过了什么,因为这不应该是正确的行为
我已经尝试将redisClient
的创建和io.on('connection')
之外的频道订阅放在('connection')上,但没有成功,结果是一样的
另一项测试
如果我广播
插座连接上的事件,如下所示:
io.on('connection', function(client)
{
client.broadcast.emit('notification','hello');
});
它工作正常,所以我认为是redis的问题。任何建议都将不胜感激。您连接了5个客户端,因此“连接”事件将触发5次。
因此,redis有5个侦听器,然后全部进行广播
有两种方法可以正确执行此操作:
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连接。我在一个项目中也做了同样的事情。唯一的区别是我从node.js发布了通知,但我没有收到任何问题。只有广播打开了套接字。非常感谢你的回答,我对它做了同样的实验。使用方法b)它向所有客户端(甚至是发送方)发出它不应该发出的消息。如果我使用broadcast
方法,它会发疯,每个发送2个通知。在方法a)中,它向所有客户端发出相同的消息,但是您所说的具有多个连接。如何将方法b)与broadcast
方法结合使用,将事件发送到除发送方之外的所有客户端?如果你不介意的话,我想和你聊聊,这对我很有用。有点离题,但我不太清楚为什么要使用PHP。您只需调用一个NodeJS Web服务来发布消息,就可以去掉开发堆栈中的一个附加部分(除非您不需要PHP来完成其他事情)。。。