从各种后端向Socket.IO客户端发送消息的最佳方法是什么?

时间:2011-09-27 03:58:02

标签: python node.js socket.io

我的设置: 我有一个现有的python脚本,使用Tweepy访问Twitter Streaming API。我还有一个网站,显示来自不同后端的其他来源的汇总实时信息。

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

如果我可以做一些像HTTP POST(从任何后端)那样简单的事情来向所有连接的客户端广播信息,那将是非常好的。

我的问题: Socket.IO客户端实现非常直接......我可以处理它。但我无法弄清楚我要求的功能是否已经存在......如果没有,那么最好的方法是什么呢?

[UPDATE]

我的解决方案:我创建了一个名为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。

2 个答案:

答案 0 :(得分:2)

我发现这种事情的最好方法是使用消息代理。就个人而言,我已经使用了RabbitMQ,这似乎符合您对另一个答案(socket.io 0.7和可扩展)的评论中提到的要求。如果您使用RabbitMQ,我建议使用节点的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);
    }

编辑:上面的示例使用了不会保留邮件的扇出交换。扇出交换可能是您的最佳选择,因为可扩展性是一个问题(即:您运行的客户端可以连接多个运行节点的盒子)。

答案 1 :(得分:1)

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

  1. Socket.IO部分,直接与客户端通信,
  2. 某种HTTP API,它接收POST请求,然后使用Socket.IO广播适当的消息。
  3. 通过这种方式,您的应用程序将成为非节点应用程序与用户浏览器之间的“桥梁”。这里的关键是使用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请求的主体并提取你需要的数据。)