服务器发送的事件轮询导致长时间延迟


Server-Sent Events Polling causing long delays

我有一个连接器,它将使用cURL和PHP调用RESP API。

我需要每秒调用一个方法来检查新消息,然后处理它们。我使用以下 2 种方法来处理消息

  1. 使用SetInterval()的AJAX轮询:每秒调用一次php脚本。这非常有效,除了我无法阻止多个SetInterval()从浏览器的不同选项卡同时运行。(我不希望用户打开 10 个浏览器选项卡,这会导致一个用户同时运行 10 个SetInterval()
  2. 服务器使用 EventSource 发送的事件:一旦队列中有新数据,服务器将发送更新浏览器。这会减慢响应时间。我对脚本的每次调用都需要大约 20+ 秒才能完成,这是一个问题。我不确定为什么会发生这种情况。

这是我SetInterval()实现

function startCalls(){
    //update the screen using Intervals
    refreshIntervalId = setInterval(function() {
        $.getJSON("index.php", {'method': 'getMessages', 'jSON': true} , function(data){
            processServerData(data);
         });
    }, 1000);
}

用户登录后,我调用此函数startCalls()

在索引.php文件中,我有这段代码要调用

if($method == 'getMessages'){
    $messaging = new ICWS'Messaging($icws);
    $messaging->processMessages();
    $myQueue = $messaging->getCallsQueue();
    echo json_encode($myQueue );
}

这是我的第二个实现"服务器发送的事件"

//Server Side Message Polling
function startPolling(evtSource){
    evtSource.addEventListener("getMessagingQueue", function(e) {
        var data = JSON.parse(e.data);
        processServerData(data)
    }, false);
}

用户登录后,我调用此函数startPolling( new EventSource("poll.php") );

为简单起见,假设我的processServerData方法如下所示

function processServerData(data){
    console.log('process the data received from the server');
}

这是我的PHP代码

<?php
    require 'autoloader.php';
    //Make sure cURL is enabled on the server
    if(!is_callable('curl_init')){
        exit('cURL is disabled on this server. Before making API calls cURL extension must be enabled.');
    }
    if( isset($_COOKIE['icws_username']) ){
        $user = trim($_COOKIE['icws_username']);
    }
    if( isset($_COOKIE['icws_password']) ){
        $pass = trim($_COOKIE['icws_password']);
    }
    if( isset($_COOKIE['icws_station']) ){
        $stationName = trim($_COOKIE['icws_station']);
    }
    if( !isset($user, $pass, $stationName) ){
        echo json_encode(array('status' => 'The IC credentials you entered are invalid')); 
        exit;
    }
    $scheme = 'http';
    $host   = 'host';
    $port   = '8018';
    $sleepTime = 1;
    $url = sprintf('%s://%s:%s@%s:%s', $scheme, $user, $pass, $host, $port);
    try {
        header("Content-Type: text/event-stream'n'n");
        session_start();
        //configure the connection
        $conf = new ICWS'Config'Config($url, $stationName); 
        //create a new instance of icws
        $attrebutes = array();
        $icws = new ICWS'Connection($conf, $attrebutes, true); 
        $messaging = new ICWS'Messaging($icws);
    ob_end_clean();
    while(true){
        header("Content-Type: text/event-stream" . PHP_EOL);
        header("Cache-Control: no-cache" . PHP_EOL);
        $messaging->processMessages();
        $result = $messaging->getCallsQueue();
        //$current = $icws->getCurrentUserStatusQueue();
        echo 'event: getMessagingQueue' . PHP_EOL;
        echo 'data: ' . json_encode( $result) . PHP_EOL;    
        echo PHP_EOL; //required  
        ob_end_flush();
        flush(); 
        sleep(1);
    }
    } catch(Exception $e){
        echo $e->getMessage();
    }

?>
服务器

似乎锁定了所有命中服务器的请求,直到无限循环被"页面刷新"停止,一旦我刷新页面,其他请求就会立即处理

为什么服务器发送事件会导致此类问题?

关于

不同类型的极化,可以在这个问题中找到一个很好的资源

一切看起来都很健壮,所以我要猜测你受到了会话锁定的打击。PHP 会话锁定会话文件,以便一次只有一个 PHP 脚本可以使用该会话;仔细想想,这是一个好主意!

会话和 SSE 的问题在于 SSE PHP 进程永远运行,因此它会永远锁定会话。如果任何其他 PHP 脚本尝试使用相同的会话运行,它将阻塞(我相信在session_start()调用时)。

这看起来像是一篇关于这个主题的好文章; 建议是一旦你知道不再需要会话,就打电话给session_write_close()。 例如,如果您只需要使用会话来检查他们之前是否授权了自己,那么之后您可以立即调用session_write_close(),其他进程不会被阻止。