创建 MDT/CAD 系统的最佳方法是什么? (AJAX,SSE,WebSocket)
What is the most optimal way to create an MDT/CAD system? (AJAX,SSE,WebSocket)
向所有正在阅读的人问好,
我在一个网站的后端工作了很长时间,该网站提供逼真的移动数据终端和计算机辅助调度系统,用于在线角色扮演。
我最初利用 AJAX 调用 setInterval,它每 100 毫秒左右刷新页面的一部分,在 PHP 端,它运行一个 SQL 查询。
正如您想象的那样,这已被证明非常缓慢,甚至最终设法搞乱会话并让人们像其他人一样登录(不要问如何……我不知道)。我读过 WebSockets 和 SSE,但我需要真正决定一种方法并将整个系统转移过来,所以我的简单问题是...
优化我的系统的最佳方法是什么?我可以在实践中举一两个例子吗?
非常感谢您的阅读,
AJAX调用示例[=35=]
JQuery
if (obs) {
obs = false;
}
$.ajax({
type:"GET",
url: "mdt.php",
data: { },
success: function(result) {
$("#mdt").html(result);
}
});
};
setInterval(function() { if (!obs) { if (!paused) { refreshmdt(); } } }, 750);
mdt.php
session_start();
include("../config.php");
include("../backend.php");
$panicsql = getConnection()->query("SELECT * FROM Units WHERE Status='PANIC'");
if ($panicsql->num_rows > 0) {
echo "<script>togglePanic('activate');</script>";
} else {
echo "<script>togglePanic('deactivate');</script>";
}
?>
<!-- Terminal -->
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2><i class="fa fa-mobile"> Terminal</i></h2>
<ul class="nav navbar-right panel_toolbox" id="terminal">
<li>
<a href="bookoff.php"><button class="btn btn-block btn-danger"><i class="fa fa-sign-out"></i> Book Off</button></a>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="x_content" id="" style="height:74.3vh;min-height:70vh;max-height:74.3vh;overflow:auto;text-align:center;">
<?php include("Ajax/status.php"); ?>
<br />
<h4><b>Change Status:</b></h4>
<br />
<p>
<a onclick="javascript:changeStatus('AVAILABLE');" class="btn btn-sq-sm btn-success">
<i class="fa fa-check fa-2x"></i><br/>
AVAILABLE
</a>
<a onclick="javascript:changeStatus('EN ROUTE');" class="btn btn-sq-sm btn-warning">
<i class="fa fa-taxi fa-2x"></i><br/>
EN ROUTE
</a>
<a onclick="javascript:changeStatus('ON SCENE');" class="btn btn-sq-sm btn-primary">
<i class="fa fa-map-marker fa-2x"></i><br/>
ON SCENE
</a>
<a onclick="javascript:changeStatus('PRISONER');" class="btn btn-sq-sm btn-info">
<i class="fa fa-user fa-2x"></i><br/>
PRISONER
</a>
<a onclick="javascript:changeStatus('UNAVAILABLE');" class="btn btn-sq-sm btn-default">
<i class="fa fa-times fa-2x"></i><br/>
UNAVAIL..
</a>
<a onclick="javascript:changeStatus('PANIC');startPanic();" class="btn btn-sq btn-block btn-danger">
<i class="fa fa-exclamation-triangle fa-1x"></i>
PANIC
</a>
</p>
<hr />
<p>
<a data-toggle="modal" data-target="#pnc" class="btn btn-sq btn-default">
<i class="fa fa-database fa-5x"></i><br/>
PNC
</a>
<a data-toggle="modal" data-target="#report" class="btn btn-sq btn-default">
<i class="fa fa-edit fa-5x"></i><br/>
REPORT
</a>
</p>
</div>
</div>
</div>
<!-- Active Incident / Observations -->
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2><i class="fa fa-comments-o"> Active Incident</i></h2>
<ul class="nav navbar-right panel_toolbox">
<li id="obsorinc">
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="x_content" id="activeInc" style="height:74.3vh;min-height:70vh;max-height:74.3vh;overflow:auto;">
<?php include("Ajax/activeInc.php"); ?>
</div>
</div>
</div>````
您现有的代码不需要太多更改即可转移到服务器发送的事件。
在前端,您拥有的 success
处理程序就是 message
事件处理程序。 (本着一步一步重构的精神,可以继续推现成的HTML。)
你在前端删除了间隔计时器,而是移到了后端。
(这样做的结果是套接字一直保持打开状态,并且 PHP 进程现在不断 运行,而不是每次轮询时启动和关闭。这可能影响扩展到大量客户端。)
后端需要更改的是将您当前拥有的内容包装在一个循环中,如下所示:
<?php
header("Content-Type: text/event-stream");
$prev_d = null;
while(true){
$d = ...
if($d != $prev_d){
echo "data:".$d."\n\n";
@ob_flush();@flush();
$prev_d = $d;
}
usleep(100000); //Poll every 0.1 seconds
}
作为第一步,您可以通过调用现有的 PHP 脚本来设置 $d
!
即使只是这些简单的更改,您的整体流程现在也变得更好了。是的,SQL 数据库仍然每 100 毫秒为每个活动用户轮询一次,但您现在仅在实际发生更改时才通过套接字发送数据。
下一步是将所有静态 HTML 放在客户端,而不是放在 PHP 脚本中。然后脚本只发回 SQL 查询的结果。这样效率更高,因此您的服务器和带宽负载会少一些。然而,主要优点是它将使系统更易于理解和维护。也更容易移植到其他语言或其他类型的客户端。
主循环会变成这样:
<?php
header("Content-Type: text/event-stream");
$prev_sql = null;
while(true){
$panicsql = getConnection()->query("SELECT * FROM Units WHERE Status='PANIC'");
if($panicsql != $prev_sql){
$d = json_encode($panicsql);
echo "data:".$d."\n\n";
@ob_flush();@flush();
$prev_sql = $panicsql;
}
usleep(100000); //Poll every 0.1 seconds
}
向所有正在阅读的人问好,
我在一个网站的后端工作了很长时间,该网站提供逼真的移动数据终端和计算机辅助调度系统,用于在线角色扮演。
我最初利用 AJAX 调用 setInterval,它每 100 毫秒左右刷新页面的一部分,在 PHP 端,它运行一个 SQL 查询。
正如您想象的那样,这已被证明非常缓慢,甚至最终设法搞乱会话并让人们像其他人一样登录(不要问如何……我不知道)。我读过 WebSockets 和 SSE,但我需要真正决定一种方法并将整个系统转移过来,所以我的简单问题是...
优化我的系统的最佳方法是什么?我可以在实践中举一两个例子吗?
非常感谢您的阅读,
AJAX调用示例[=35=]
JQuery
if (obs) {
obs = false;
}
$.ajax({
type:"GET",
url: "mdt.php",
data: { },
success: function(result) {
$("#mdt").html(result);
}
});
};
setInterval(function() { if (!obs) { if (!paused) { refreshmdt(); } } }, 750);
mdt.php
session_start();
include("../config.php");
include("../backend.php");
$panicsql = getConnection()->query("SELECT * FROM Units WHERE Status='PANIC'");
if ($panicsql->num_rows > 0) {
echo "<script>togglePanic('activate');</script>";
} else {
echo "<script>togglePanic('deactivate');</script>";
}
?>
<!-- Terminal -->
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2><i class="fa fa-mobile"> Terminal</i></h2>
<ul class="nav navbar-right panel_toolbox" id="terminal">
<li>
<a href="bookoff.php"><button class="btn btn-block btn-danger"><i class="fa fa-sign-out"></i> Book Off</button></a>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="x_content" id="" style="height:74.3vh;min-height:70vh;max-height:74.3vh;overflow:auto;text-align:center;">
<?php include("Ajax/status.php"); ?>
<br />
<h4><b>Change Status:</b></h4>
<br />
<p>
<a onclick="javascript:changeStatus('AVAILABLE');" class="btn btn-sq-sm btn-success">
<i class="fa fa-check fa-2x"></i><br/>
AVAILABLE
</a>
<a onclick="javascript:changeStatus('EN ROUTE');" class="btn btn-sq-sm btn-warning">
<i class="fa fa-taxi fa-2x"></i><br/>
EN ROUTE
</a>
<a onclick="javascript:changeStatus('ON SCENE');" class="btn btn-sq-sm btn-primary">
<i class="fa fa-map-marker fa-2x"></i><br/>
ON SCENE
</a>
<a onclick="javascript:changeStatus('PRISONER');" class="btn btn-sq-sm btn-info">
<i class="fa fa-user fa-2x"></i><br/>
PRISONER
</a>
<a onclick="javascript:changeStatus('UNAVAILABLE');" class="btn btn-sq-sm btn-default">
<i class="fa fa-times fa-2x"></i><br/>
UNAVAIL..
</a>
<a onclick="javascript:changeStatus('PANIC');startPanic();" class="btn btn-sq btn-block btn-danger">
<i class="fa fa-exclamation-triangle fa-1x"></i>
PANIC
</a>
</p>
<hr />
<p>
<a data-toggle="modal" data-target="#pnc" class="btn btn-sq btn-default">
<i class="fa fa-database fa-5x"></i><br/>
PNC
</a>
<a data-toggle="modal" data-target="#report" class="btn btn-sq btn-default">
<i class="fa fa-edit fa-5x"></i><br/>
REPORT
</a>
</p>
</div>
</div>
</div>
<!-- Active Incident / Observations -->
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2><i class="fa fa-comments-o"> Active Incident</i></h2>
<ul class="nav navbar-right panel_toolbox">
<li id="obsorinc">
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="x_content" id="activeInc" style="height:74.3vh;min-height:70vh;max-height:74.3vh;overflow:auto;">
<?php include("Ajax/activeInc.php"); ?>
</div>
</div>
</div>````
您现有的代码不需要太多更改即可转移到服务器发送的事件。
在前端,您拥有的 success
处理程序就是 message
事件处理程序。 (本着一步一步重构的精神,可以继续推现成的HTML。)
你在前端删除了间隔计时器,而是移到了后端。
(这样做的结果是套接字一直保持打开状态,并且 PHP 进程现在不断 运行,而不是每次轮询时启动和关闭。这可能影响扩展到大量客户端。)
后端需要更改的是将您当前拥有的内容包装在一个循环中,如下所示:
<?php
header("Content-Type: text/event-stream");
$prev_d = null;
while(true){
$d = ...
if($d != $prev_d){
echo "data:".$d."\n\n";
@ob_flush();@flush();
$prev_d = $d;
}
usleep(100000); //Poll every 0.1 seconds
}
作为第一步,您可以通过调用现有的 PHP 脚本来设置 $d
!
即使只是这些简单的更改,您的整体流程现在也变得更好了。是的,SQL 数据库仍然每 100 毫秒为每个活动用户轮询一次,但您现在仅在实际发生更改时才通过套接字发送数据。
下一步是将所有静态 HTML 放在客户端,而不是放在 PHP 脚本中。然后脚本只发回 SQL 查询的结果。这样效率更高,因此您的服务器和带宽负载会少一些。然而,主要优点是它将使系统更易于理解和维护。也更容易移植到其他语言或其他类型的客户端。
主循环会变成这样:
<?php
header("Content-Type: text/event-stream");
$prev_sql = null;
while(true){
$panicsql = getConnection()->query("SELECT * FROM Units WHERE Status='PANIC'");
if($panicsql != $prev_sql){
$d = json_encode($panicsql);
echo "data:".$d."\n\n";
@ob_flush();@flush();
$prev_sql = $panicsql;
}
usleep(100000); //Poll every 0.1 seconds
}