将消息从PHP发送到Node.js

将消息从PHP发送到Node.js

问题描述:

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

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

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

建议似乎是通过HTTP接口与节点交谈,就像任何其他客户端一样。你可以在PHP中使用卷曲通过HTTP交谈节点

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

特别是看到这个帖子从马特帕迪

我遇到过类似的问题,想告诉用户的新的 注释被添加到一个错误中,并且类似的通知实际上只能从PHP发送到我的节点服务器。我做了以下 (道歉,如果在 发送时发现所有乱码和未格式化,如果发生这种情况,我很乐意将代码粘贴到其他地方):首先,您需要使用PHP中的cURL。我写了一个函数我 类是这样的:

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

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

在您的节点的应用程序,你可能有这样的:

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) { 
     ... 
} 

等等等等,我还没有在一段时间进行了测试,实际上是代码块 在我的节点服务器上被注释掉了,所以我希望我在这里粘贴 的作品 - 总的来说,这个概念已经被证明,我认为它会适用于你的 。无论如何,只是想确定你知道这是几个月如此 我不确定我为什么注释掉。我写的代码花费了很少的研究 - 比如在cURL中设置'Expect:'标题 - 当它终于起作用时,我很兴奋。让我知道你是否需要任何 额外的帮助。

最佳,

马特·帕迪

+0

不错的链接!非常感谢您的帮助。 – Sparky1 2012-04-06 22:14:58

+2

虽然这可能会在理论上回答这个问题,但我们希望您在答案中包含链接文章的基本部分,并提供[链接供参考](http://meta.stackexchange.com/q/8259)。如果做不到这一点,答案就会受到链接腐败的威胁。 – Kev 2012-09-24 23:07:01

+0

同意。现在重要的信息就是答案。没有更多的风险。 – 2012-11-01 12:16:25

有点晚了,但你可以使用Redis的发布/订阅机制,以一种非常简单而有效的方法您的节点客户端通信。你所需要做的就是在你的服务器上安装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 
}) 

这是可扩展性?(针对@磨憨 - 辛格)

在谈到可扩展性,你需要考虑你的基础设施的架构和你的特殊需要,但这里有一个快速的答案: 我一直在使用这种机构的变型的高没有问题的流量的实时应用程序,但这里是你应该是什么小心:

  1. 的Redis的Pub/Sub是不是一个排队系统,这意味着,如果你的节点过程进行了所有已发送而这是消息羽绒将会丢失。

  2. 如果您有超过1位订阅者,他们都会收到相同的消息并处理它,如果您有多个节点进程监听处理实时逻辑的相同redis数据库,请注意这一点(有个简单的方法去解决这个虽然)

关于这个系统的好处是,你不需要任何补充到现有的基础架构,可以立即上手,它的速度非常快,它的行为完全像一个HTTP服务器。

您可以通过以下更具扩展性的选择方案:

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

这个冗长的编辑点在于,没有魔术可伸缩解决方案这样的东西,您需要权衡您的选项并查看哪一个对您的用例最有效。 在我看来,如果您现在开始构建您的第一个迭代,请选择您感觉舒适的任何选项,编写非常干净的代码,并且在开始缩放时将很容易进行更改,这就是我所做的完成:)

+2

谢谢,非常有用 – Eric 2015-01-23 03:10:11

+0

高流量应用程序如何?这种机制是否可销售?我想用我的实时应用程序使用redis和laravel。请让我知道它是否成功。 – 2015-08-27 12:03:11

+1

我编辑了我的答案来回复你的问题。 – user1128896 2015-08-29 09:43:21

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

第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消息给节点服务器,服务器回复ok。

在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的发射完全不同,所以您需要查看它是否与您现有的代码兼容。