来自 PHP 的 SSE 回显以随机间隔重复

SSE echo from PHP duplicating at random intervals

我正在尝试设置一个 PHP 服务器发送事件,它工作正常。但是在随机的时间间隔内,它会重复推送相同的数据。

这里有一个快速场景来阐明我所描述的内容:假设我在 1:00:00 处插入了一条数据库记录。记录的数据按原样推送。但是,在 1:03:00 处,该记录的数据被第二次推送。然后在 1:03:17 处再次被推送。我现在显示了 3 个记录实例。

为什么会发生这种情况,为什么会随机发生?

我增加了 php 执行时间,但问题仍然存在。

在浏览器控制台中,我收到此错误:net::ERR_INCOMPLETE_CHUNKED_ENCODING。

我在客户端有这个:

  <script>
    var source = new EventSource('pdo_updates.php');
    var pdo_updates;
    source.onmessage = function(e) {
        pdo_updates = e.lastEventId + '' + e.data + '<br>';
        document.getElementById("videoID").innerHTML += pdo_updates;
    };
    evtSource.close();
  </script>

这是服务器端的:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0');
function send_msg($id, $msg) {
    echo "data: $msg" . PHP_EOL;
    echo PHP_EOL;
    ob_flush();
    flush();
}
    $last_event_id = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : False);
    if ($last_event_id == 0) {
        $last_event_id = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : False);
    }

    $last_id = 0;
    try {
        $conn = new PDO('mysql:host=localhost;dbname=my_db', $username, $password);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

        while(1) {
            $id  = $last_event_id != False ? $last_event_id : $last_id;
            $stmt = $conn->prepare("SELECT id, message FROM messages WHERE id > :id ORDER BY id DESC LIMIT 1");
            $result = $stmt->execute(array('id' => $id));
            $stmt->bindValue('id', $id);

            if ($result) {
                while($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
                    if ($data) {
                        send_msg($data['id'], $data['message']);
                        $last_id = $data['id'];
                    }
                }
            }
            sleep(1);
        }       
    } catch(PDOException $e) {
        echo 'ERROR: ' . $e->getMessage();
    }

因此,在尝试了几乎所有与 keepalive 相关的 header 和每个 apache 超时调整配置之后,我最终 运行 捕获了一个数据包。我发现远程端正在触发 TCP 重置。我的网站支持 Cloudflare,一旦我禁用 Cloudflare,问题 部分 就消失了。 TCP session 每 100 秒刷新一次,这会导致最后一条消息再次出现。这是导致浏览器控制台错误的原因:net::ERR_INCOMPLETE_CHUNKED_ENCODING

然而,与此同时,我的提交代码出现了问题。但我不是 100% 确定为什么。

$.ajax({
       type: "POST",
       url: url,
       data: $("#submitmessage").serialize(), // serializes the form's elements.
       success: function(data)
       {
         $("#myvideo").val("");
       }
     });

提交后我需要清除输入字段中的值。从那以后我没有任何重复。