Symfony流式响应(Server Sent Event)阻塞请求

4
我使用Symfony的StreamedResponse实现了Server Sent Event(SSE)。当事件发生时,消息将保存在会话中,并通知用户。 问题是当包含客户端代码的页面被执行时,它会阻塞应用程序的所有Web请求,直到SSE连接由于最大执行时间而关闭。
服务器端代码:
public function notificationAction() {
    $response = new StreamedResponse(function() {
        while(true) {
            $message = "";

            $messagesNotification = $this->get('session')->getFlashBag()->get('message_notification');; // code that search notifications from session
            if(count($messagesNotification)>0){
                foreach ( $messagesNotification as $messageNotification ) {
                    $message .= "data: " . messageNotification  . PHP_EOL;
                }
                $message .= PHP_EOL;
                echo $message;
                ob_flush();
                flush();

            }
            sleep(8);
        };

    });

    $response->headers->set('Content-Type', 'text/event-stream');
    $response->headers->set('Cache-Control', 'no-cache');
    return $response;
}

客户端代码:

<script>
    var path = '/path';
    var source = new EventSource(path);
    source.onmessage = function(e) {
        // notification html
    };
    source.onerror = function(e) {
        // notification html
    };
</script>

我想知道这是否是一个良好的 SSE 实现,并且如何使 SSE 调用不阻塞请求。
我正在使用 Symfony 2.6 和 Firefox 浏览器。
感谢您的帮助。
2个回答

5

使用$this->get('session')隐式调用的session_start()会锁定会话文件(如果你使用默认的文件会话处理程序),直到你通过session_write_close()写入。

$this->get('session')->save()

只有在 sleep(8); 之上使用,该文件才会被解锁。


Federico,这是Symfony中等效于session_write_close()的方法吗?(例如,请参见https://dev59.com/tIzda4cB1Zd3GeqPhAnE#30878764) - Darren Cook
@jherencia 最好在新问题中提出此问题(另外,如果此回答可以解决“阻止请求”问题,请接受此回答)。将错误消息翻译成英语,并尝试在其他浏览器中(例如Chrome)进行测试,以查看是否仅限于Firefox。 - Darren Cook
1
@DarrenCook,是的,它是。 - Federkun
@Federico,非常抱歉之前的信息没有翻译。翻译后的信息是“Firefox无法连接到地址为...的服务器”。我在Chrome中尝试了一下,但它只是在一段时间后给出错误,而不像Firefox那样给出消息。 这是我第一次发布问题,所以我没有足够的积分将其标记为有用的答案。谢谢。 - jherencia
如果我有不同的会话处理程序,比如mysql呢? - Ramratan Gupta
显示剩余2条评论

1
如果你想使用SSE技术,你不需要将代码放入循环中以便能够持续监听,因为永久监听在SSE技术中是隐含的。然后移除循环,它是不必要的。然而,这种技术与Symfony不兼容,相反,可以使用建立在SSE技术基础上并且与Symfony非常好集成的Mercury协议,除非你计划修改Symfony源代码,否则SSE将无法正常工作。 Symfony文档中有关Mercury的链接:https://symfony.com/doc/current/mercure.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接