2016-12-01 49 views
0

在我的web应用程序(symfony3)中,我试图集成一个实时通知系统。 我选择具有这种配置做到了这一点: 服务器的NodeJS 服务器redis的 socket.io socket.io-PHP极 - 发射极(PHP adaptater直接从PHP EMIT通知)使用socket.io和redis实时通知

app.js(服务器节点)

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

io.sockets.on('connection', function (socket) { 
    console.log('user connected!'); 
}); 

io.adapter(redis({ host: 'localhost', port: 6379 })); 
server.listen(8081, 'myhost'); 

测试控制器

public function testAction(Request $request) 
{ 
    $notification = 'A message has been received by the server!<br />' 
    $form = $this->createFormBuilder()->getForm(); 
    $form->handleRequest($request); 
    if ($form->isValid()) { 
     $redis = new \Redis(); 
     $redis->connect('127.0.0.1', '6379'); 
     $emitter = new SocketIO\Emitter($redis); 
     $emitter->emit('notification', $notification); 
     $response = new JsonResponse(); 
     $response->setData(array(
      'notification' => $notification 
     )); 
     return $response; 
    } 
    return $this->render('@PMPlatform/Test/test.html.twig', array(
     'form' => $form->createView() 
    )); 
} 

客户端视图

$(document).ready(function() { 
    // Getting socket 
    var socket = io('http://myhost:8081'); 
    // Listening on notification from server 
    socket.on('notification', function (data) { 
     $('.server').append('qsfdqsfdqsdfqsfdqsfd'); 
    }); 
    // Listener on form submit event 
    $(document).on('submit', '.form', function(e) { 
     e.preventDefault(); 
     $.ajax({ 
      type: 'POST', 
      url: '/app_dev.php/test', 
      data: $(this).serialize(), 
      success : function(response){ 
       $('.client').append('A message has been sent to server from this client!<br />'); 
      }, 
      error : function(response){ 
       console.log('Something went wrong.'); 
      }, 
      cache: false 
     }); 
     return false; 
    }); 
}); 

好吧,这个简单的测试工作正常:当我从正确的视图提交表单时,通知显示在此页面上的所有客户端。

1-现在我想让一个用户只能向另一个用户发送通知(当用户发表评论时,该帖子的作者收到通知)。我如何做到这一点?

2-如果作者没有连接,如何在作者连接时保存通知以显示它?

+0

如果你问我,这是一个相当广泛的问题。有很多方法可以实现这一点。一种方法是将其存储到数据库并在页面加载或w/e中检索它。 –

回答

1

对于第一个问题,在以某种方式维护的服务器中,例如,通过套接字重新列出所有连接的客户端。但是,关键是在连接到服务器时传递用户的ID。现在,您的socket.io服务器中的用户完全可以通过其id识别出来。

io.sockets.on('connection', function (socket) { 
    console.log(socket); 
}); 

如果您查看连接附带的套接字对象,那么您将获得刚刚连接的用户的标识。 然后,当您想向该用户发送通知时,您只需在redis中搜索相应的套接字以发送要发送通知的用户标识。当你实例化你的发射器$emitter = new SocketIO\Emitter($redis);你将不得不在redis中搜索那个特定的套接字 - 在redis中按用户ID搜索 -

对于第二个问题,我不会进入此功能的websockets。每次用户连接时,您都必须在数据库中搜索是否有任何待处理通知,并发送给他。这可以为少量用户完成,而不会导致繁重的计算使用,但这不会扩展。 为此,我将:

  • 在Redis的搜索连接的用户
  • 如果没有连接,保存到数据库中的新通知。
  • 当用户再次连接时,向API发送标准的HTTP请求,并向他发送所有待处理的通知,处理它们并进行必要的更改。

希望它能帮助!

编辑

我忘了解释你如何通过连接上的数据。在客户端只需要:var socket = io('http://216.157.91.131:8080/', { userId: "myUserId" });。很简单,不是吗?

+0

好的,谢谢你的解释!所以如果我理解正确,我不能将通知存储在redis数据库中?我必须将实时通知系统与传统的存储方式(如doctrine ymsql)结合起来? –

+0

当然你可以!但这取决于有多少客户端连接到您的服务器。如果您认为您的基础架构可以毫无问题地处理,那么只要每次获得'io.sockets.on('connection')'事件时,都可以在redis中搜索用户的待处理通知。但是你将不得不通过NodeJS服务器的这个用户套接字发出一个通知,你将无法从PHP中完成。 – Jorge

+0

好吧,但在你的文章中,你是什么意思关于“如果没有连接,保存到数据库中的新通知。” ?你谈论Redis的数据库或传统的数据库像MySQL? –