将消息从PHP发送到Node.js

如何发送消息从PHP到node.js? 我有一个运行PHP和Node.js的Linux服务器。

当用户完成一个事务(通过PHP),我想发送一个消息从PHP到node.js. 然后节点将通过套接字连接更新客户端。

从php向node.js发送less量数据而不破坏node.js的性能的好方法是什么?

build议似乎是通过HTTP接口与节点交谈,就像任何其他客户端一样。 您可以通过HTTP使用cURL在php中与节点通话

请参阅: http : //groups.google.com/group/socket_io/browse_thread/thread/74a76896d2b72ccc/216933a076ac2595?pli=1

特别是从Matt Pardee看到这篇文章

我面临着一个类似的问题,想要让用户知道添加到一个bug中的新注释,以及类似的通知,这些通知实际上只能从PHP发送到我的Node服务器。 我做了以下事情(道歉,如果发送时出现乱码和无格式,如果发生这种情况,我很乐意将代码粘贴到其他地方):首先,您需要使用PHP中的cURL。 我为我的class级写了这样一个函数:

function notifyNode($type, $project_id, $from_user, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1'); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); curl_setopt($ch, CURLOPT_PORT, 8001); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_POST, true); $pf = array('f' => $type, 'pid' => $project_id, 'user_from' => $from_user, 'data' => array()); foreach($data as $k => $v) { $pf['data'][$k] = $v; } curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($pf)); curl_exec($ch); curl_close($ch); } 

你会注意到我在同一台服务器上发送了cURL请求,因为PHP和NodeJS都在那里运行,你的里程可能会有所不同。 我设置这个代码连接到的端口是8001(这是我的节点服务器运行的端口,以及socket.io服务器连接的端口)。 这发送一个HTTP POST请求与编码后的字段。 这是非常标准的curl的东西。

在你的Node应用程序中,你可能有这样的东西:

 var server = http.createServer(function(req, res) {}); server.listen(8001); var io = io.listen(server, { transports: ['websocket', 'flashsocket', 'xhr-polling'] }); ... 

那么我们在这里做的是扩展http.createServer部分,以监听来自我们的本地主机(“127.0.0.1”)的连接。 然后createServer代码变成:

 var server = http.createServer(function(req, res) { // Check for notices from PHP if(res.socket.remoteAddress == '127.0.0.1') { if(req.method == 'POST') { // The server is trying to send us an activity message var form = new formidable.IncomingForm(); form.parse(req, function(err, fields, files) { res.writeHead(200, [[ "Content-Type", "text/plain"] , ["Content-Length", 0] ]); res.write(''); res.end(); //sys.puts(sys.inspect({fields: fields}, true, 4)); handleServerNotice(fields); }); } } }); 

从那里你可以实现你的handleServerNotice函数..

 function handleServerNotice(data) { ... } 

等等。我还没有testing过这一段时间,事实上,代码块已经在我的节点服务器上被注释掉了,所以我希望我粘贴在这里的工作 – 一般来说,这个概念已被certificate,我认为它会为你工作。 无论如何,只是想确定你知道这是几个月,所以我不知道为什么我评论。 我写的代码花了一些研究 – 比如在cURL中设置“Expect:”标题 – 当它终于起作用时,我非常兴奋。 让我知道你是否需要任何额外的帮助。

最好,

马特Pardee

有点晚了,但是你可以使用Redis Pub / Sub机制以一种非常简单有效的方式与你的节点客户端进行通信。 所有你需要做的就是在你的服务器上安装redis。

在PHP方面,初始化Redis然后发布消息

 $purchase_info = json_encode(array('user_id' =>$user_id, 'purchase_information'=>array('item'=>'book','price'=>'2$')); $this->redis->publish('transaction_completed', $purchase_info); 

在node.js端

 var redis = require('redis'); var purchase_listener = redis.createClient(); purchase_listener.subscribe('transaction_completed'); purchase_listener.on('message', function(channel, message){ var purchase_data = JSON.parse(message); user_id = purchase_data.user_id; purchase_info = purchase_data.purchase_information; // Process the data // And send confirmation to your client via a socket connection }) 

这是可扩展的吗? (回应@ mohan-singh)

在谈到可扩展性时,您需要考虑您的基础架构的体系结构和您的特定需求,但是这里有一个快速的答案:我已经在高stream量的实时应用程序中使用了这种机制的一个变体,但是这里是您应该小心的:

  1. Redis PUB / SUB不是一个排队系统,这意味着如果你的节点进程closures了发送的所有消息,但是当它关​​闭的时候将会丢失。

  2. 如果你有超过1个订阅者,他们将会收到相同的消息并处理它,如果你有多于一个节点进程监听同一个redis db来处理你的实时逻辑,那么要注意这一点(有一些简单的方法去这个虽然)

关于这个系统的好处是,你不需要添加任何东西到你现有的基础设施上,并且可以立即开始,速度非常快,而且它的行为和HTTP服务器一样。

以下是更多可扩展选项的替代scheme:

  1. 使用自主托pipe的快速消息队列服务器(ActiveMQ,RabbitMQ,beanstalkd …)服务器来处理你的消息逻辑之间的PHP和节点,这些往往是快速的,但随着负载的增加,你失去了一点性能,必须维护/扩展你的消息服务器,并注意跨地区的重复,这不是一件容易和愉快的事情(取决于你喜欢做什么)。
  2. 使用托pipe的消息传递队列服务器(IronMQ,SQS …)其中的一些(IronMQ)速度非常快,对您的用例来说会很好,但是会给您的代码库带来一些(小的)复杂性。
  3. 使用群集节点服务器与Redis构build消息队列: https : //davidmarquis.wordpress.com/2013/01/03/reliable-delivery-message-queues-with-redis/
  4. 在VPN内使用HTTP与节点服务器进行通信。 一旦你看到你的stream量高峰,你只需要负载平衡你的节点服务器,并根据需要添加尽可能多的无状态服务器,并发送POST消息到负载均衡器。

这个冗长的编辑点在于,没有这样一个魔术可伸缩的解决scheme,你需要权衡你的select,看看哪一个对你的用例最好。 在我看来,如果你现在开始构build你的第一个迭代,select你喜欢的任何选项,编写非常干净的代码,当你开始扩展时,它将会很容易改变,这就是我所做的:)

第1步。获取PHP发射器: https : //github.com/rase-/socket.io-php-emitter

 $redis = new \Redis(); // Using the Redis extension provided client $redis->connect('127.0.0.1', '6379'); $emitter = new SocketIO\Emitter($redis); $emitter->emit('new question', '<b>h<br/>tml</b>'); 

添加到您的index.js:

 var redis = require('socket.io-redis'); io.adapter(redis({ host: 'localhost', port: 6379 })); io.on('connection', function(socket){ socket.on('new question', function(msg) { io.emit('new question', msg); }); }); 

添加这样的东西到你的index.html

 socket.on('new question', function(msg) { $('body').append( msg ); }); 

我发现这样的问题可以简单地通过使用Express框架来解决。 让我们假设PHP发送一个json消息到节点服务器和服务器回复正常。

在app.js中

 var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); var bodyParser = require('body-parser') app.use(bodyParser.json()); app.post('/phpcallback', function(req, res) { var content = req.body; console.log('message received from php: ' + content.msg); //to-do: forward the message to the connected nodes. res.end('ok'); }); http.listen(8080, function(){ var addr = http.address(); console.log('app listening on ' + addr.address + ':' + addr.port); }); 

在test.php

 <?php $data = array("name" => "Robot", "msg" => "Hi guys, I'm a PHP bot !"); $data_string = json_encode($data); $ch = curl_init('http://localhost:8080/phpcallback'); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($data_string)) ); echo curl_exec($ch)."\n"; curl_close($ch); ?> 

在这里,我们还有一个更详细的例子,在这个例子中,一个php脚本可以向特定聊天室的用户发送消息。

https://github.com/lteu/chat


我个人对Redis方法的印象:繁琐。 你需要同时运行Apache,nodeJS和Redis三台服务器。 而PubSub机制与socket.io的发射完全不同,所以你需要看看它是否与你现有的代码兼容。

我们通过使用消息队列来完成。 有很多像radis( https://github.com/mranney/node_redis )或0mq( http://zeromq.org/ )的解决scheme。 它允许发送消息给订阅者(例如从php到nodejs)。