duanou9758
duanou9758
2017-06-05 02:35

实时传感器数据作为Python发送事件(SSE)从PHP到PHP?

已采纳

I'm in the process of updating a web app presenting real-time sensor data, which in it's current first iteration does this by continuous AJAX polling. However, in order to make this more like a 'true real-time' app, I would like it to be event-based.

I've been reading up on event-based techniques, and based on the fact that the real-time communication only has to go one way (server - > client), I have chosen to go with Server-Sent Events (SSE) for now instead of something like websockets. As described here on the Mozilla Docs, this is easily implemented on the server side with something like (a little simplified):

<?php
// SSEscript.php
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream

");

while (1) {
   if ($new_data_available) {
      echo "data:". $data;
   } 

   sleep($short_time_to_spare_cpu);
}
?>

and on the client side with:

<script>
var evtSource = new EventSource("SSEscript.php");

evtSource.onmessage = function(e) {
   var data = e.data;
   // Do something with data object
} 
</script>

All the above works fine for me. However, the sensor data is initially retrieved by a Python script running continuously on the server, so how do I transfer the sensor data from the Python script to the PHP script IMMEDIATELY when it is retrieved, so that an event can be generated and sent?

Can I do something like depicted below? : scenario1

At the same time all new data is stored in a MySQL db, so I could of course make the PHP script query the db really often for new entries, but there has to be a smarter way. So can I make 2.1 and 2.2 in the image happen at the same time?

All the answers I could find in here describes how data can be transferred by making the PHP execute the Python script, but that is not what I want as this has to run whether or not a user asks for data.

Is a kind of socket the way to go, and if so, can you point me in the direction of how to do so? I hope you can help me out!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • douyu7618 douyu7618 4年前

    I use redis to do the signalling between python and redis. After python do all the stuffs, rpush a token (or the latest data) into a redis queue. In the PHP I use a while(true) loop to hold the request and redis lpop(queue,timeout) to wait for the token, and send data out, something like this:

    <?php
        require __DIR__.'/predis-1.0/autoload.php';
        header("Content-Type: text/event-stream");
        header("Cache-Control: no-cache");
        header("Connection: keep-alive");
    
        $lastId = isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? 
                  $_SERVER["HTTP_LAST_EVENT_ID"] : null;
        if (isset($lastId) && !empty($lastId) && is_numeric($lastId)) {
            $lastId = intval($lastId);
            $lastId++;
        }
    
        $index = isset($_GET['index']) ? $_GET['index'] : null;
    
        echo "retry: 2000
    ";
    
        $client = new Predis\Client();
        while (true) {
            $data = $client->blpop('queue',5);
            if ($data) {
                error_log("$index : " . strlen($data));
                sendMessage($lastId, $data);
                $lastId++;
            }
        }
    
        function sendMessage($id, $data) {
            echo "id: $id
    ";
            echo "data: $data
    
    ";
            ob_flush();
            flush();
        }
    
    点赞 评论 复制链接分享

相关推荐