从不同后端向Socket.IO客户端发送消息的最佳方式是什么

2 投票
2 回答
1324 浏览
提问于 2025-04-17 03:09

我的设置:

我有一个现成的Python脚本,使用Tweepy来访问Twitter的实时数据接口。同时,我还有一个网站,可以展示来自不同后端的实时汇总信息。

我理想的场景:

我希望能通过Socket.IO把实时的推文和其他信息的实时更新发布给我的连接用户。

如果我能简单地通过HTTP POST(从任何后端)来广播信息给所有连接的客户端,那就太好了。

我的问题:

Socket.IO的客户端实现非常简单……我能搞定。但是我不确定我想要的功能是否已经存在……如果没有,最好的实现方式是什么呢?

[更新]

我的解决方案:我创建了一个叫Pega.IO的项目,正好实现了我想要的功能。基本上,它让你像往常一样使用Socket.IO(0.8+),但你可以使用HTTP POST来发送消息给连接的用户。

它使用Express网络服务器和Redis作为后端。从理论上讲,这应该很容易扩展——我会继续为这个项目贡献力量。

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

就这么简单。你可以从任何后端通过HTTP POST向你的Pega.IO服务器发送信息。

2 个回答

1

为什么不把你的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端口上有一个网络服务器,可以用来监听网络请求(你可以使用像Express这样的框架,或者其他很多框架来解析POST请求的内容,并提取你需要的数据)。

2

我发现处理这类事情的最好方法是使用消息中间件。个人来说,我用过RabbitMQ,它似乎符合你在其他回答中提到的要求(socket.io 0.7和可扩展性)。如果你选择RabbitMQ,我建议使用npm中的amqp模块来配合Node.js,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()

在Node.js端,最基本的连接代码可能看起来像这样:

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

补充说明:上面的示例使用的是一种不持久化消息的fan-out交换机。由于可扩展性是个问题(也就是说,你可能有多个Node.js服务器可以供客户端连接),fan-out交换机可能是你最好的选择。

撰写回答