最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

PHP Server Sent Event overload on While loop - Stack Overflow

programmeradmin0浏览0评论

I'm creating an infopage for work that updates "live".

Now i came across Server Sent Events.

I managed to put data on the screen but the update was every 3 seconds. (After looking online it appears i created a disconnect and the default retry time was 3 seconds)

So i found a sollution that in theory should work but when putting it live, it creates an overload on the server side.

<?php

        // make session read-only
        session_start();
        session_write_close();

        // disable default disconnect checks
        ignore_user_abort(true);

        // set headers for stream
        header("Content-Type: text/event-stream");
        header("Cache-Control: no-cache");
        header("Access-Control-Allow-Origin: *");

        // Is this a new stream or an existing one?
        $lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
        if ($lastEventId == 0) {
            $lastEventId = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : 0);
        }

        echo ":" . str_repeat(" ", 2048) . "\n"; // 2 kB padding for IE
        echo "retry: 1000\n";

        // start stream
        while(true){
            if(connection_aborted()){
                exit();
            } else{

                // here you will want to get the latest event id you have created on the server, but for now we will increment and force an update
                $latestEventId = $lastEventId+1;

                if($lastEventId < $latestEventId){
                    echo "id: " . $latestEventId . "\n";
                    echo "data: Howdy (".$latestEventId.") \n\n";
                    $lastEventId = $latestEventId;
                    ob_flush();
                    flush();
                } else{
                    // no new data to send
                    echo ": heartbeat\n\n";
                    ob_flush();
                    flush();
                }
            }
    
            // 2 second sleep then carry on
            sleep(1);
        }
        
?>

It appears that the while(true) loop is the problem ...

Unfortunatly i couldn't find the correct way to use Server Side events with a connection that stays open.

Is there someone that knows a sollution for this?

i tried using this script without while loop (which works) BUT thats because the client side keeps reconnecting after every 3 seconds, so basically the connection opens, closes, opens, closes

I'm creating an infopage for work that updates "live".

Now i came across Server Sent Events.

I managed to put data on the screen but the update was every 3 seconds. (After looking online it appears i created a disconnect and the default retry time was 3 seconds)

So i found a sollution that in theory should work but when putting it live, it creates an overload on the server side.

<?php

        // make session read-only
        session_start();
        session_write_close();

        // disable default disconnect checks
        ignore_user_abort(true);

        // set headers for stream
        header("Content-Type: text/event-stream");
        header("Cache-Control: no-cache");
        header("Access-Control-Allow-Origin: *");

        // Is this a new stream or an existing one?
        $lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
        if ($lastEventId == 0) {
            $lastEventId = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : 0);
        }

        echo ":" . str_repeat(" ", 2048) . "\n"; // 2 kB padding for IE
        echo "retry: 1000\n";

        // start stream
        while(true){
            if(connection_aborted()){
                exit();
            } else{

                // here you will want to get the latest event id you have created on the server, but for now we will increment and force an update
                $latestEventId = $lastEventId+1;

                if($lastEventId < $latestEventId){
                    echo "id: " . $latestEventId . "\n";
                    echo "data: Howdy (".$latestEventId.") \n\n";
                    $lastEventId = $latestEventId;
                    ob_flush();
                    flush();
                } else{
                    // no new data to send
                    echo ": heartbeat\n\n";
                    ob_flush();
                    flush();
                }
            }
    
            // 2 second sleep then carry on
            sleep(1);
        }
        
?>

It appears that the while(true) loop is the problem ...

Unfortunatly i couldn't find the correct way to use Server Side events with a connection that stays open.

Is there someone that knows a sollution for this?

i tried using this script without while loop (which works) BUT thats because the client side keeps reconnecting after every 3 seconds, so basically the connection opens, closes, opens, closes

Share Improve this question edited Feb 2 at 22:25 Peter Cordes 366k49 gold badges717 silver badges977 bronze badges asked Feb 2 at 19:46 Thomas D.Thomas D. 111 bronze badge 9
  • If it helps, MDN has a PHP example and it's also in Github: github/mdn/dom-examples/tree/main/server-sent-events -- You may want to compare this with your script and perhaps find some inspiration how you can re-structure your while loop that you have already identified as problematic. Just FYI. // github/hhxsv5/php-sse – hakre Commented Feb 2 at 20:03
  • @hakre the problem is that the while loop is the problem... i tried multiple codes with the same set-up – Thomas D. Commented Feb 2 at 21:22
  • 1 Then it's perhaps with your server and php settings. As the examples show, there are implications on buffering. Have you used the network tab of your browsers web-developer tools to track whats going on connection wise? – hakre Commented Feb 2 at 21:37
  • @hakre the page stays in loading stage, which is normal i guess since it can't reach the end of the php file because of the While loop – Thomas D. Commented Feb 2 at 22:03
  • Which page? And there are a couple of loading stages.... also not clear if you do logging on the client side or not. Still the code in question looks as if it could be reduced and some parts are missing (MRE) Please edit in all the relevant details. – hakre Commented Feb 2 at 22:11
 |  Show 4 more comments

1 Answer 1

Reset to default 0

Where is this hosted? If your own, the server logs might give a clue. If shared hosting, long-running processes are usually killed after a certain amount of time.

The other main troubleshooting idea is to watch what is happening in the Network tab in developer tools in the browser. It will show what data is sent, and if it is the server-side or client-side that aborts the connection.

Also try connecting via curl, to confirm the problems happen there.

I think there is a bug in your code as shown:

echo ": heartbeat\n\n";

It should read:

echo "data: heartbeat\n\n";

I don't know if that is triggering the problems you see, but I'd fix it. (I'd also recommend putting the datestamp in, rather than a fixed string. It will help troubleshooting.)

发布评论

评论列表(0)

  1. 暂无评论