只在内核之后返回响应.终止事件



我对kernel.terminate的理解是在响应返回给客户端后触发

在我的测试中,情况似乎并非如此。如果我在内核上调用的函数中加入一个sleep(10),终止。浏览器也等待10秒。处理似乎在发送响应之前就已经发生了。

我有以下配置:

calendar:
    class: AcmeCalendarBundleServiceCalendarService
    arguments: [ @odm.document_manager, @logger, @security.context, @event_dispatcher ]
    tags:
        - { name: kernel.event_subscriber }

我的订阅者类:

class CalendarService implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'kernel.terminate' => 'onKernelTerminate'
        );
    }
    public function onKernelTerminate()
    {
        sleep(10);
        echo "hello";
    }
}

这似乎与Symfony没有发送Content-Length标头有关。如果生成了,响应就会正确返回。

// app_dev.php
...
$kernel = new AppKernel('dev', true);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
// --- START EDITS ---
$size = strlen($response->getContent());
$response->headers->set('Content-Length', $size);
$response->headers->set('Connection', 'close');
// ---- END EDITS ----
$response->send();
$kernel->terminate($request, $response);

这个问题原来是非常具体的我的设置(Nginx, PHP-FCGI, Symfony)。

有几个问题导致了这个问题:

  1. Symfony不包含Content-LengthConnection: close
  2. PHP-FCGI不支持fastcgi_finish_request函数Nginx缓冲PHP-FCGI的响应,因为Gzip在

解决方案是从PHP-FCGI切换到PHP-FPM以获得对fastcgi_finish_request的支持。Symfony在执行内核终止逻辑之前会在内部调用这个函数,从而最终关闭连接。

另一个解决这个问题的方法是在Nginx上关闭Gzip,但这对我来说不是一个真正的选择。

相关内容

最新更新