如何使用带触发器的服务器发送事件?

时间:2017-08-30 14:50:21

标签: php mysql sql ajax

我正在考虑迁移我的通知系统,该通知系统使用ajax池到服务器发送的事件的方式类似于:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$sql = "SELECT name,body FROM notification where id='user1'";
...
echo 'data: ' . json_encode($arrayResult) . "\n\n";
$conn->close();
flush();
?>

我的问题是,这似乎是不断向DB提出查询(与ajax池类似),这似乎会变得非常密集。

您建议更改服务器端代码,以便它不会不断地汇集数据库,而只会在插入通知后查询它?

2 个答案:

答案 0 :(得分:1)

发生的事情是,默认情况下,浏览器将在3秒后重新打开连接,您的脚本将再次运行并查询数据库。我看到的另一个问题是,即使自上次检查后没有新的通知,您的SQL查询也将始终返回结果。更好的查询将仅选择最近的通知。你有三个简单的选择

设置retry参数

通过向浏览器发送带有第一条消息的retry值,您可以控制浏览器等待重新打开连接的时间:

echo "retry: 60000\n"; // reopen the connection in 60 seconds
echo 'data: ' . json_encode($arrayResult) . "\n\n";

使用带暂停的无限循环

不是让你的脚本快速执行到最后并让浏览器在3秒后重新打开连接,你可以在你控制的频率的循环中进行数据库检查

set_time_limit(0); // remove any time limit to script execution

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header("Connection: keep-alive");

while(true){
  $sql = 'SELECT...'; // alter your query to only fetch recent notifications
  // fetch results and put in $arrayResult
  if(!empty($arrayResult)) echo 'data: ' . json_encode($arrayResult) . "\n\n";
  ob_flush(); flush();
  sleep(60); // sleep for 60 seconds
}

使用内存缓存

内存缓存可以在一个脚本执行中存储通知,并在另一个脚本执行中检索它们。所以你的脚本会:

  • 检查缓存中是否存在属于当前用户的通知
  • 如果找到,则回显通知并将其从缓存中删除(或设置SENT标志)
  • 别睡觉,然后循环

我使用了memcache但还有其他人。这确实需要您在Web服务器上安装新软件,但这可能就是我要做的。

答案 1 :(得分:0)

在这种情况下,您需要直接在将数据库插入数据库的代码中拦截通知(从而使数据库短路)。

更常规的方法是使用消息代理。