2016-12-01 5 views
0

In meiner Web-App (symfony3) versuche ich ein Echtzeit-Benachrichtigungssystem zu integrieren. I zu wählen, erfolgt dies mit dieser Konfiguration: Server NodeJS Server redis Socket.io socket.io-PHP-Emitter (php Adaptater für Emit Benachrichtigung direkt von php)Echtzeit-Benachrichtigung mit socket.io und redis

app.js (Serverknoten)

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'); 

Prüfsteuerung

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() 
    )); 
} 

Client Ansicht

$(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; 
    }); 
}); 

Ok dieser einfache Test funktioniert gut: Wenn ich das Formular aus der richtigen Ansicht absende, wird eine Benachrichtigung an alle Clients angezeigt, die sich auf dieser Seite befinden.

1- Jetzt möchte ich einen Benutzer in der Lage sein, eine Benachrichtigung nur an einen anderen Benutzer zu senden (wenn ein Benutzer einen Beitrag kommentiert, der Autor des Beitrags erhielt eine Benachrichtigung). Wie kann ich das machen?

2- Wenn der Autor nicht angeschlossen ist, Wie kann ich die Meldung zu speichern, es zu zeigen, wenn der Autor wieder verbindet?

+0

Das ist eine ziemlich große Frage, wenn Sie mich fragen. Es gibt viele Möglichkeiten, dies zu erreichen. Eine Möglichkeit besteht darin, sie in einer Datenbank zu speichern und sie beim Laden der Seite oder w/e abzurufen. –

Antwort

1

Für Ihre erste Frage in dem Server, den Sie in irgendeiner Weise halten, redis zum Beispiel eine Liste aller angeschlossenen Clients von ihren Sockeln. Aber das Wichtigste ist hier, eine ID des Benutzers zu übergeben, wenn er sich mit dem Server verbindet. Jetzt haben Sie Ihre Benutzer in Ihrem socket.io Server durch ihre ID identifiziert.

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

Wenn Sie an der Socket-Objekt suchen, die mit einer Verbindung kommt, wird es Sie die ID des Benutzers haben, wurde gerade angeschlossen. Wenn Sie dann eine Benachrichtigung an diesen Benutzer senden möchten, müssen Sie nur in Redis nach dem entsprechenden Socket für die Benutzer-ID suchen, der Sie eine Benachrichtigung senden möchten. Wenn Sie Ihren Emitter $emitter = new SocketIO\Emitter($redis); instanziieren, müssen Sie in Redis nach dem bestimmten Socket suchen - Suche in redis nach Benutzer-ID -

Für die zweite Frage werde ich nicht in WebSockets für diese Funktion gehen. Jedes Mal, wenn ein Benutzer eine Verbindung herstellt, müssen Sie in der Datenbank suchen, wenn er eine ausstehende Benachrichtigung hat, und an ihn senden. Dies kann für eine kleine Anzahl von Benutzern durchgeführt werden, ohne dass eine hohe Rechenleistung erforderlich ist, aber dies skaliert nicht. Zu diesem Zweck werde ich:

  • Suche in redis für den angeschlossenen Benutzer
  • Wenn die neue Benachrichtigung in Datenbank speichert nicht verbunden.
  • Wenn der Benutzer erneut eine Verbindung herstellt, führen Sie eine Standard-HTTP-Anforderung an die API aus und senden Sie ihm alle ausstehenden Benachrichtigungen zu, bearbeiten Sie diese und nehmen Sie die erforderlichen Änderungen vor.

Hoffe, es hilft!

EDIT

vergaß ich zu erklären, wie Sie Daten über die Verbindung übergeben. Auf dem Client tun Sie einfach: var socket = io('http://216.157.91.131:8080/', { userId: "myUserId" });. Einfach, oder?

+0

Ok danke für deine Erklärung! Also, wenn ich richtig verstehe, kann ich die Benachrichtigung in redes db nicht speichern? Ich muss das Echtzeit-Benachrichtigungssystem mit einer traditionellen Speichermethode verbinden (wie Doktrin ymsql)? –

+0

Natürlich können Sie! Aber es hängt davon ab, wie viele Clients sich mit Ihren Servern verbinden. Wenn Sie der Meinung sind, dass Ihre Infrastruktur problemlos funktionieren kann, suchen Sie in Redis nach ausstehenden Benachrichtigungen des Benutzers, immer wenn Sie ein "io.sockets.on ('connection')" - Ereignis erhalten. Aber Sie müssen eine Benachrichtigung von diesem Benutzer-Socket vom NodeJS-Server aus senden, Sie können es nicht von PHP aus tun. – Jorge

+0

Ok ok, aber in Ihrem Beitrag, was meinst du mit "Wenn nicht verbunden, speichern Sie in der Datenbank die neue Benachrichtigung." ? redest db oder eine traditionelle db wie mysql? –

Verwandte Themen