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

时间:2017-04-02 06:47:47

标签: php mysql server-sent-events

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

这是一个快速的场景来澄清我所描述的内容:假设我在1:00:00插入了db记录。记录的数据按原样推送。但是,在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();
    }

1 个答案:

答案 0 :(得分:2)

因此,在尝试几乎所有与keepalive相关的标头和每个apache超时调整配置后,我最终运行了一个数据包捕获。我发现远程端正在触发TCP重置。我的网站背后是Cloudflare,一旦我禁用Cloudflare,问题部分就消失了。 TCP会话每100秒刷新一次,并且会在发生这种情况时再次显示最后一条消息。这导致浏览器控制台错误:|-------------------------------------|----//---| |-------------------------------------|----//---| |-------------------------------------|----//---|

但与此同时,我的提交代码中存在问题。但我不是百分之百确定原因。

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

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