2016-12-01 80 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? –