从不同后端向Socket.IO客户端发送消息的最佳方式是什么
我的设置:
我有一个现成的Python脚本,使用Tweepy来访问Twitter的实时数据接口。同时,我还有一个网站,可以展示来自不同后端的实时汇总信息。
我理想的场景:
我希望能通过Socket.IO把实时的推文和其他信息的实时更新发布给我的连接用户。
如果我能简单地通过HTTP POST(从任何后端)来广播信息给所有连接的客户端,那就太好了。
我的问题:
Socket.IO的客户端实现非常简单……我能搞定。但是我不确定我想要的功能是否已经存在……如果没有,最好的实现方式是什么呢?
[更新]
我的解决方案:我创建了一个叫Pega.IO的项目,正好实现了我想要的功能。基本上,它让你像往常一样使用Socket.IO(0.8+),但你可以使用HTTP POST来发送消息给连接的用户。
它使用Express网络服务器和Redis作为后端。从理论上讲,这应该很容易扩展——我会继续为这个项目贡献力量。
在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 个回答
为什么不把你的Node应用分成两个部分呢:
- 一个是Socket.IO部分,负责和客户端直接沟通,
- 另一个是某种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请求的内容,并提取你需要的数据)。
我发现处理这类事情的最好方法是使用消息中间件。个人来说,我用过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交换机可能是你最好的选择。