【问题标题】:What is the best way to send messages to Socket.IO clients from various back-ends从各种后端向 Socket.IO 客户端发送消息的最佳方式是什么
【发布时间】:2011-09-27 03:58:02
【问题描述】:

我的设置: 我有一个使用 Tweepy 访问 Twitter 流 API 的现有 python 脚本。我还有一个网站,显示来自各种后端的其他来源的聚合实时信息。

我的理想场景: 我想使用 Socket.IO 向我的连接用户发布实时推文以及我的其他信息的实时更新。

如果我能做一些简单的事情,比如 HTTP POST(从任何后端)向所有连接的客户端广播信息,那就太好了。

我的问题: Socket.IO 客户端实现非常简单……我可以处理。但我无法弄清楚我要求的功能是否已经存在......如果不存在,实现它的最佳方法是什么?

[更新]

我的解决方案:我创建了一个名为 Pega.IO 的项目,它可以满足我的需求。基本上,它允许您像往常一样使用 Socket.IO (0.8+),但您可以使用 HTTP POST 向连接的用户发送消息。

它使用带有 Redis 后端的 Express Web 服务器。从理论上讲,这应该很容易扩展——我将继续为这个项目做出贡献。

Pega.IO - github

要在 Ubuntu 上安装,您只需运行以下命令:

curl http://cloud.github.com/downloads/Gootch/pega.io/install.sh | sh

这将创建一个监听端口 8888 的 Pega.IO 服务器。

启动并运行后,只需:

HTTP POST http://your-server:8888/send

使用如下所示的数据:

channel=whatever&secretkey=mysecret&message=hello+everyone

仅此而已。从任何后端到您的 Pega.IO 服务器的 HTTP POST。

【问题讨论】:

    标签: python node.js socket.io


    【解决方案1】:

    我为这类事情找到的最佳方法是使用消息代理。就个人而言,我为此使用了 RabbitMQ,这似乎符合您对另一个答案(socket.io 0.7 和可扩展)的评论中提到的要求。如果你使用 RabbitMQ,我推荐用于 node 的 amqp 模块,可通过 npm 获得,以及用于 Python 的 Pika 模块。

    使用 pika 的 Python 连接器示例。此示例接受单个 json 序列化参数:

        def amqp_transmit(message):
            connection = pika.AsyncoreConnection(pika.ConnectionParameters(host=settings.AMQP_SETTINGS['host'],
                port=settings.AMQP_SETTINGS['port'],
                credentials=pika.PlainCredentials(settings.AMQP_SETTINGS['username'],
                        settings.AMQP_SETTINGS['pass'])))
            channel = connection.channel()
            channel.exchange_declare(exchange=exchange_name, type='fanout')
            channel.queue_declare(queue=NODE_CHANNEL, auto_delete=True, durable=False, exclusive=False)
            channel.basic_publish(exchange=exchange_name,
                    routing_key='',
                    body=message,
                    properties=pika.BasicProperties(
                            content_type='application/json'),
                    )
            print ' [%s] Sent %r' %(exchange_name, message)
            connection.close()
    

    节点端的非常基本的连接代码可能如下所示:

        var connection = amqp.createConnection(
            {host: amqpHost,
            port: amqpPort,
             password: amqpPass});
    
        function setupAmqpListeners() {
            connection.addListener('ready', amqpReady)
            connection.addListener('close', function() {
                console.log('Uh oh! AMQP connection failed!');
            });
            connection.addListener('error', function(e) {throw e});
        }
    
        function amqpReady(){
            console.log('Amqp Connection Ready');
            var q, exc;
            q = connection.queue(queueName,
                {autoDelete: true, durable: false, exclusive: false},
                function(){
                    console.log('Amqp Connection Established.');
                    console.log('Attempting to get an exchange named: '+exchangeName);
                    exc = connection.exchange(exchangeName,
                        {type: 'fanout', autoDelete: false},
                        function(exchange) {
                            console.log('Amqp Exchange Found. ['+exchange.name+']');
                            q.bind(exc, '#');
                            console.log('Amqp now totally ready.');
                            q.subscribe(routeAmqp);
                        }
                    );
                }
            );
        }
    
    
        routeAmqp = function(msg) {
                console.log(msg);
                doStuff(msg);
        }
    

    编辑:上面的示例使用了不持久化消息的扇出交换。扇出交换可能是您的最佳选择,因为可扩展性是一个问题(即:您正在运行多个客户端可以连接到的运行节点的盒子)。

    【讨论】:

    • 看起来 Socket.IO 内置了对 redis 的支持——虽然我不知道如何使用它......也许我在文档中遗漏了它,但我不知道看不到任何关于如何水平扩展 Socket.IO 0.7+ 的明确示例
    • 我想我在这里有点跑题了......我想回答的问题的主要部分是关于设置 Socket.IO 以接受来自任何后端的 HTTP POST 请求广播消息而不是通过 javascript 客户端
    • 问题是对单个节点框的 http POST 请求不可扩展。当您需要多个运行 nodejs 的机器才能正确响应请求时,这不起作用...您是否想要可扩展,或者您是否想要一个保证永远无法扩展到运行 nodejs 的单台机器之外的解决方案?如果是后者,您可以只使用 nodejs 模块 Express(包含在默认的 nodejs 安装中)和 python 模块 urllib。如果他们的文档中有任何令人困惑的地方,我很乐意提供代码示例。
    • 绝对希望它扩大规模——我认为我们不应该选择吗?如果有一种方法可以对单个节点框进行 HTTP 发布,以模拟您通过 javascript 进行正常发出或广播时会发生的情况——它应该希望能够发送到所有节点框上的客户端,不是吗? ?
    • 可以(虽然我强烈建议不要这样做)使用 HTTP 请求在节点盒之间进行通信。消息队列解决方案专门用于以可扩展的方式执行您想要执行的操作。另一种可能比 HTTP 更有效但不如完整 MQ 解决方案有效的替代方法是使用 github.com/remy/Socket.io-node-client 并让 Node 实例相互连接。 (注意:自从 socket.io v0.6 以来我没有使用过这个)
    【解决方案2】:

    为什么不编写你的 Node 应用程序,以便有两个部分:

    1. 直接与客户端通信的 Socket.IO 部分,以及
    2. 某种 HTTP API,它接收 POST 请求,然后使用 Socket.IO 广播适当的消息。

    通过这种方式,您的应用程序成为非 Node 应用程序和用户浏览器之间的“桥梁”。这里的关键是将 Socket.IO 用于它的用途——与浏览器的实时通信——并在应用程序的其他部分依赖其他 Node 技术。

    [更新]

    我目前不在开发环境中,所以我无法为您提供一个工作示例,但一些伪代码看起来像这样:

    http = require('http');
    io   = require('socket.io');
    
    server = http.createServer(function(request, response) {
      // Parse the HTTP request to get the data you want
      io.sockets.emit("data", whatever); // broadcast the data to Socket.IO clients
    });
    server.listen(8080);
    socket_server = io.listen(server);
    

    有了这个,您将在端口 8080 上拥有一个 Web 服务器,您可以使用它来监听 Web 请求(您可以使用诸如 Express 之类的框架或许多其他框架来解析 POST 请求的正文并提取您需要的数据)。

    【讨论】:

    • 这个食谱会很棒......听起来确实是一个很好的方法。我确信有很多新的 node.js 人员(包括我自己)会从实际的实现示例中学到很多东西。需要记住的几件事......它需要扩展(redis?)并且需要使用 Socket.IO 0.7+(用于 hybi-10 支持)
    猜你喜欢
    • 2010-10-13
    • 1970-01-01
    • 2015-04-05
    • 2013-09-09
    • 2012-05-24
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    相关资源
    最近更新 更多