php - 如何同步 PHP 和 NodeJS 与 Redis 并按顺序获取数据

标签 php node.js redis

我有一个示例代码用于进行实验,试图在一个简单的聊天示例中思考“如何“同步””nodejs 和 php。

这是我的 NodeJS 服务器:

var redis       = require('redis'),
    subscriber  = redis.createClient(),
    publisher   = redis.createClient();

//var sckio = require('socket.io').listen(8888);
var http = require('http');
var querystring = require('querystring');

var WebSocketServer = require('ws').Server

var ENCODING = 'utf8';

var tCounter = 0;

/* #################################### */

// Event on "subscribe" to any channel
subscriber.on("subscribe", function (channel, count) {

    // Publish to redis server Test Message
    publisher.publish("chat", "NODEJS MESSAGE");

});

// Suscrib to redis server
subscriber.on('message', function (channel, json) {
    console.log('SUB: ' + channel + ' | ' + json);

    console.log('PHP PUSH TO REDIS, AND NODE CAPTURE REDIS PUSH: ' + (getMicrotime(true) - tCounter));       

});

subscriber.subscribe('chat'); // Subs to "mysql" channel


/*
var clients = [];
sckio.sockets.on('connection', function (socket) {

  clients.push(socket);
  publisher.publish("chat", "User connected");

  socket.on('message', function (from, msg) {

    publisher.publish("chat", msg);

    clients.forEach(function (client) {
      if (client === socket) return;
      client.send(msg);
    });

  });

  socket.on('disconnect', function () {

    clients.splice(clients.indexOf(socket), 1);
    publisher.publish("chat", "User disconnected");

  });

});
*/

var wss = new WebSocketServer({port: 8888, timeout : 500});
var wsClients = [];

wss.on('connection', function(ws) {


    ws.AUTH_ID = Math.random();
    wsClients.push(ws);

    publisher.publish("chat", "User enter");

    ws.on('message', function(message) {

        wsClients.forEach(function (client) {
           client.send(ws.AUTH_ID + ' ' + message);
        });

        tCounter = getMicrotime(true);
        console.log('CALL TO PHP: ' + tCounter);

        PostCode('CODE TO PHP FROM NODE', function() {
            wsClients.forEach(function (client) {
               client.send('PHP SAVE DATA');
            });

        });

    });

    ws.on('close', function(message) {

      wsClients.splice(wsClients.indexOf(ws), 1);
      publisher.publish("chat", "User left");

    });

    ws.send('HELLO USER!');

});    

function getMicrotime(get_as_float) {
    var now = new Date().getTime() / 1000;
    var s = parseInt(now, 10);

    return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
}

function PostCode(codestring, callback) {

  // Build the post string from an object
  var post_data = querystring.stringify({
      'output_format': 'json',
        'js_code' : codestring
  });

  // An object of options to indicate where to post to
  var post_options = {
      host: '127.0.0.1',
      port: '80',
      path: '/NodeJS/chat_system/php_system.php',
      method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': post_data.length
        }
  };

  // Set up the request
  var post_req = http.request(post_options, function(res) {
      res.setEncoding(ENCODING);
      res.on('data', function (chunk) {

          console.log('Response FROM PHP: ' + chunk);
          if (typeof callback == 'function') {
            callback(chunk);
          }

      });
  });

  // post the data
  post_req.write(post_data);
  post_req.end();

}

这是我的 PHP 服务器

require 'Predis/Autoloader.php';
Predis\Autoloader::register();



function pushToRedis($data) {

    try {

        $redis = new Predis\Client(array(
            'scheme' => 'tcp',
            'host'   => '127.0.0.1',
            'port'   => 6379,
        ));       

    } catch (Exception $e) {
        echo "Couldn't connected to Redis";
        echo $e->getMessage();
        return false;
    }

    $json = json_encode($data);
    $redis->publish("chat", $json);

    return true;

}


pushToRedis('PHP PUSH TO REDIS!');

header('Content-Type: application/json');
echo json_encode(array('response' => print_r(array($_REQUEST, $_SERVER), true)));

还有我的客户:

<!DOCTYPE html>
<html>
<head>

<meta charset="utf-8">
<title>WebSockets - Simple chat</title>

<style>

    .chat { width: 400px; height: 250px; overflow-y: scroll; }

</style>

</head>
<body>


<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

<script>

    var connection = new WebSocket('ws://127.0.0.1:8888');

    $(document).ready(function() {

        /*
        var socket = io.connect('http://127.0.0.1:8888');
        socket.on('message', function (data) {
          alert(data);
        });
        socket.send('HELLO!');
        */


        connection.onopen = function () {
            console.log('connected!');
        };

        connection.onerror = function (error) {

        };  

        connection.onmessage = function (message) {
            $('.chat').append(message.data + '<br>');
            $('.chat').scrollTop($('.chat')[0].scrollHeight);
        };

        $('input[name="text"]').on('keydown', function(e) {

            if (e.keyCode === 13) {
                var msg = $(this).val();
                connection.send(msg);
                $(this).val('').focus();
            }

        });




    });


</script>


<div class="chat">

</div>

<input type="text" name="text">

</body>
</html>

问题是当网络繁忙时 PHP 通过 Redis 将响应返回给 NodeJS 的顺序。

例如:我从 de javascript 客户端发送更多消息,然后,NodeJS 调用每条消息到 PHP,PHP 将数据保存在 MYSQL 中,并调用 Redis,NodeJS 检测 Redis 推送并更新客户端。但是,在某些情况下,如果我从 Javascript 客户端循环发送一些消息(for(0-10000)),我不会以相同的顺序回复其他客户端,以防在客户端中获得 200,201,300,202,320,203 之类的数字。

我认为这是因为 PHP 延迟响应。

我的问题是如何以正确的顺序管理响应以更新客户端?因为这个问题会导致客户端以错误的顺序接收聊天消息。

最佳答案

但是为什么要用php你可以直接用nodejs的mysql包给mysql发数据

您可以通过以下方式安装 mysql 包: npm 安装 mysql

连接由: mysql = require('mysql'),

连接 = mysql.createConnection({ 主机:'本地主机', 用户:'用户名', 密码:'密码', database: '数据库名称', 端口:3306 }),

并使用 :

抛出查询

var q=connection.query('从表中选择 *);

关于php - 如何同步 PHP 和 NodeJS 与 Redis 并按顺序获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19794504/

相关文章:

node.js - 使用 Nodejs 将参数传递给 CloudFormation 函数

mysql - Sails + MySQL 重新连接并尝试

mysql - 我应该在服务器端(或客户端)处理俚语/坏词屏蔽以获得更好的性能吗?

php - Laravel 下的负载均衡器 + 集中式 Redis session 服务器

php - 计算页面上执行的 MySQL 查询数

php - 如何在 Codeigniter 中使用 includes 和 base 模板?

node.js - 我在 iisnode windows web 应用程序上托管了我的 Loopback 4 应用程序,从那里获取端口作为 Loopback 4 无法理解的管道

redis - 我应该如何处理 celery Tasks 中的 redis 连接?

php - 使用 if 和 else 从数据库中查找并显示某些字符串

php - 在 PHP 中,究竟什么是 curl 句柄?