你好,可能正在读的人,
我在网站的后端工作了很长时间,该网站提供了一个现实的移动数据终端和计算机辅助调度系统,用于在线角色扮演。
我最初在setInterval上使用AJAX调用,实际上每100毫秒刷新一次页面的一部分,而在PHP端,它运行SQL查询。
您可以想象,这被证明是非常缓慢的,并且甚至设法弄乱了会话并以其他人的身份登录(最终不要问...我不知道)。我已经阅读了有关WebSockets和SSE的文章,但是我需要真正地决定一种方法并转移整个系统,所以我的简单问题是...
优化系统的最佳方法是什么?我可以在实践中举两个例子吗?
非常感谢您阅读,
AJAX通话示例
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
!即使有了这些简单的更改,您的总体流程现在也要好得多。是的,仍然对每个活动用户每100毫秒对SQL数据库进行一次轮询,但是现在您仅在实际发生更改时才通过套接字发送数据。
下一步是将所有静态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 }