我正在更新呈现实时传感器数据的Web应用程序,其中当前的第一次迭代通过连续的AJAX轮询来完成此操作。 但是,为了使这更像是一个真正的实时'应用程序,我希望它是基于事件的。
我一直在阅读基于事件的技术,并且基于实时通信只需要一种方式(服务器 - >客户端)的事实,我选择使用Server-现在发送事件(SSE)而不是像websockets这样的东西。 正如here on the Mozilla Docs所述,这很容易在服务器端实现,例如(稍微简化):
<?php
// SSEscript.php
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream\n\n");
while (1) {
if ($new_data_available) {
echo "data:". $data;
}
sleep($short_time_to_spare_cpu);
}
?>
并在客户端使用:
<script>
var evtSource = new EventSource("SSEscript.php");
evtSource.onmessage = function(e) {
var data = e.data;
// Do something with data object
}
</script>
以上所有对我来说都很好。 但是,传感器数据最初是由在服务器上连续运行的Python脚本检索的,因此在检索传感器数据时如何将传感器数据从Python脚本立即传输到PHP脚本,以便生成并发送事件?
同时所有新数据都存储在MySQL数据库中,因此我当然可以让PHP脚本经常查询数据库以获取新条目,但必须有更聪明的方法。那么我可以在图像中同时发生2.1和2.2吗?
我在这里找到的所有答案都描述了如何通过让PHP执行Python脚本来传输数据,但这不是我想要的,因为无论用户是否要求数据都必须运行。
是一种插座方式,如果是这样,你能指出我的方向吗? 我希望你能帮助我!
答案 0 :(得分:1)
我使用redis在python和redis之间进行信令。在python完成所有工作之后,将令牌(或最新数据)转发到redis队列中。在PHP中,我使用while(true)循环来保存请求,并使用redis lpop(queue,timeout)等待令牌,然后发送数据,如下所示:
<?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\n";
$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\n";
echo "data: $data\n\n";
ob_flush();
flush();
}