Symfony StreamedResponse Server Sent事件阻止请求

时间:2015-10-26 17:12:47

标签: symfony server-sent-events

我在Symfony中使用StreamedResponse实现了服务器发送事件(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 个答案:

答案 0 :(得分:4)

您使用session_start()隐含的

$this->get('session')将锁定会话的文件(如果您使用本机文件会话处理程序,默认情况下),直到您使用

编写它
$this->get('session')->save()

只有这样文件才会被解锁。尝试在sleep(8);上方使用它。

答案 1 :(得分:1)

如果您想使用sse技术,则无需将代码放入循环中就可以连续进行侦听,因为sse技术中隐含了永久侦听功能。然后删除循环是没有必要的。但是,此技术与Symfony不兼容,而是使用基于sse技术构建的汞协议,该协议与symfony很好地集成在一起,除非您计划修改symfony sse的来源,否则将不起作用。 symfony文档中有关汞https://symfony.com/doc/current/mercure.html

的链接