【问题标题】:Real time notification with socket.io and redis使用 socket.io 和 redis 进行实时通知
【发布时间】:2017-04-16 07:50:51
【问题描述】:

在我的网络应用程序 (symfony3) 中,我尝试集成一个实时通知系统。 我选择使用此配置来完成此操作: 服务器节点JS 服务器redis 套接字.io socket.io-php-emitter(用于直接从 php 发出通知的 php 适配器)

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-如果作者未连接,我如何保存通知以在作者连接时显示它?

【问题讨论】:

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

标签: php node.js redis socket.io symfony


【解决方案1】:

对于您的第一个问题,在您以某种方式维护的服务器(例如 redis)中,通过其套接字列出所有已连接客户端的列表。但是,这里的关键是在连接到服务器时传递用户的 id。现在,您的 socket.io 服务器中的用户已完全由他们的 id 标识。

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

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

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

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

希望对你有帮助!

编辑

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

【讨论】:

  • 好的,谢谢您的解释!因此,如果我理解正确,我不能将通知存储在 redis db 中吗?我必须将实时通知系统与传统的存储方式(如学说 ymsql)结合起来?
  • 当然可以!但这取决于有多少客户端连接到您的服务器。如果您认为您的基础架构可以毫无问题地处理,只需在每次收到 io.sockets.on('connection') 事件时在 redis 中搜索用户的待处理通知。但是你必须通过这个用户套接字从 NodeJS 服务器发出一个通知,你将无法从 PHP 中做到这一点。
  • 好的,但是在您的帖子中,“如果未连接,请将新通知保存到数据库中”是什么意思。 ?你说的是redis db还是mysql之类的传统db?
  • 你可以使用任何你喜欢的持久化系统。如果您使用 redis,请注意它是一个内存键值数据库,尽管可以启用持久性到磁盘。您将需要编写待处理的通知,例如作为 userID 的键和带有通知本身的 stringify json 的值。
  • 好的,在客户端视图中,当我尝试使用 var socket = io('216.157.91.131:8080', { userId: "myUserId" }); 保存用户 id 变量时或 socket.userId = "test";当我检查日志并搜索 userId 时,没有匹配项。所以这里有一个问题,因为 var 没有添加到套接字对象中。
猜你喜欢
  • 2018-12-12
  • 1970-01-01
  • 2014-01-31
  • 2013-05-05
  • 2012-05-03
  • 2016-01-12
  • 2018-08-02
  • 2016-07-21
  • 1970-01-01
相关资源
最近更新 更多