将消息从PHP发送到Node.js

将消息从PHP发送到Node.js,php,node.js,Php,Node.js,如何将消息从php发送到node.js?我有一个运行php和node.js的linux服务器 当用户完成一个事务(通过php)时,我想从php向node.js发送一条消息。然后,节点将通过套接字连接更新客户端 在不影响node.js性能的情况下,从php向node.js发送少量数据的好方法是什么?建议通过HTTP接口与node通信,就像其他客户端一样。您可以在php中使用cURL通过HTTP与节点通信 见: 特别是,请看马特·帕迪的这篇文章 我面临着一个类似的问题,那就是想让用户了解新的应用程序

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

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


在不影响node.js性能的情况下,从php向node.js发送少量数据的好方法是什么?

建议通过HTTP接口与node通信,就像其他客户端一样。您可以在php中使用cURL通过HTTP与节点通信

见:

特别是,请看马特·帕迪的这篇文章

我面临着一个类似的问题,那就是想让用户了解新的应用程序 注意添加到一个bug上,类似的通知可能 只能从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);
}
//You might have something like this - just included to show object setup
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);

server.on("connection", function(s) {
    //If connection is from our server (localhost)
    if(s.remoteAddress == "::ffff:127.0.0.1") {
        s.on('data', function(buf) {
            var js = JSON.parse(buf);
            io.emit(js.msg,js.data); //Send the msg to socket.io clients
        });
    }
});
您会注意到,我在同一台服务器上发送了cURL请求 PHP和NodeJ都在那里运行,您的里程可能会有所不同。港口 我将此代码设置为连接到is 8001(这是我的节点服务器的端口 正在运行,并且socket.io服务器连接到的端口)。这 发送带有已编码POST字段的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:”标题——我 当它最终成功时,我非常激动。如果需要,请告诉我 额外的帮助

最好的

马特·帕迪


虽然有点晚,但您可以使用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
})
这是可伸缩的吗?(回应@mohan singh)

在谈到可扩展性时,您需要考虑基础架构的体系结构和特定需求,但这里有一个快速的答案: 我一直在高流量实时应用程序上使用这种机制的变体,没有出现问题,但以下是您应该注意的事项:

  • Redis PUB/SUB不是一个排队系统,这意味着如果您的节点进程停止运行,则在停止运行时发送的所有消息都将丢失

  • 如果发布服务器有多个订阅服务器,它们都将接收相同的消息并进行处理,请注意,如果有多个节点进程在侦听同一个redis db以处理实时逻辑,则要注意这一点(不过有一些简单的方法可以解决这一问题)

  • 这个系统的好处在于,您不需要向现有的基础架构添加任何内容,并且可以立即启动,它非常快,而且其行为与HTTP服务器完全相同

    以下是更多可扩展选项的备选方案:

  • 使用自托管的快速消息队列服务器(ActiveMQ、RabbitMQ、beanstalkd…)来处理php和节点之间的消息传递逻辑,它们往往很快,但随着负载的增加,您会损失一些性能,并且必须维护/扩展消息传递服务器,并注意跨区域复制,这不是一件容易和愉快的事情(取决于你喜欢做什么)
  • 使用托管消息队列服务器(IronMQ、SQS…)其中一些(IronMQ)非常快,对于您的用例来说非常有用,但会给您的代码库带来一些(较小的)复杂性
  • 使用带有群集节点服务器的Redis构建消息传递队列:
  • 在VPN中使用HTTP与节点服务器通信。一旦看到流量激增,您只需对节点服务器进行负载平衡,并根据需要添加尽可能多的无状态服务器,然后向负载平衡器发送POST消息
  • 这篇冗长的编辑的要点是,没有神奇的可伸缩解决方案,您需要权衡您的选项,看看哪一个最适合您的用例。
    在我看来,如果您现在开始构建您的第一个迭代,请选择您喜欢的任何选项,编写非常干净的代码,当您开始扩展时,它将非常容易更改,这就是我所做的:)

    我们通过使用消息队列来完成。有很多解决方案,如radis()或0mq()。它允许向订阅者发送消息(例如从php发送到nodejs)

    第1步。获取PHP发射器:

    在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脚本可以向特定聊天室的用户发送消息



    我个人对Redis方法的印象是:笨重。您需要同时运行Apache、nodeJS和Redis这三台服务器。PubSub机制与socket.io的emit机制完全不同,因此您需要查看它是否与现有代码兼容。

    我正在寻找一个非常简单的
    <?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);
    
    ?>
    
    //You might have something like this - just included to show object setup
    var app = express();
    var server = http.createServer(app);
    var io = require('socket.io').listen(server);
    
    server.on("connection", function(s) {
        //If connection is from our server (localhost)
        if(s.remoteAddress == "::ffff:127.0.0.1") {
            s.on('data', function(buf) {
                var js = JSON.parse(buf);
                io.emit(js.msg,js.data); //Send the msg to socket.io clients
            });
        }
    });
    
    function sio_message($message, $data) {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        $result = socket_connect($socket, '127.0.0.1', 8080);
        if(!$result) {
            die('cannot connect '.socket_strerror(socket_last_error()).PHP_EOL);
        }
        $bytes = socket_write($socket, json_encode(Array("msg" => $message, "data" => $data)));
        socket_close($socket);
    }