【问题标题】:How can I use server sent events with trigger?如何将服务器发送的事件与触发器一起使用?
【发布时间】:2017-08-30 14:50:21
【问题描述】:

我正在考虑以类似于以下方式将使用 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();
?>

不过我的问题是,这似乎会不断地对数据库进行查询(以类似于 ajax 池的方式),这似乎会变得非常密集。

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

【问题讨论】:

  • 你找到这个解决方案了吗?只要我们使用 PHP,我认为 SSE 只是另一种轮询方法。还是没有效果。

标签: php mysql sql ajax


【解决方案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 服务器上安装新软件,但我可能会这样做。

【讨论】:

    【解决方案2】:

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

    更传统的做法是使用消息代理。

    【讨论】:

    • 我正在考虑使用 Redis 缓存,它会在插入时创建并在缓存中插入通知数组。那么服务器端事件只会查询缓存,不会超载数据库。
    • 是的,这样会更好。 Redis 实际上可以用作消息代理:redis.io/topics/pubsub
    猜你喜欢
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 2013-01-11
    • 2022-01-22
    • 2014-07-17
    相关资源
    最近更新 更多