仅在kernel.terminate事件之后返回响应

anu*_*shr 13 fastcgi nginx symfony

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

在我的测试中,看起来并非如此.如果我sleep(10)在kernel.terminate中调用了一个函数.浏览器也等待10秒钟.处理似乎在发送响应之前发生.

我在配置中有以下内容:

calendar:
    class: Acme\CalendarBundle\Service\CalendarService
    arguments: [ @odm.document_manager, @logger, @security.context, @event_dispatcher ]
    tags:
        - { name: kernel.event_subscriber }
Run Code Online (Sandbox Code Playgroud)

我的订阅者类:

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

    public function onKernelTerminate()
    {
        sleep(10);
        echo "hello";
    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

这似乎与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);
Run Code Online (Sandbox Code Playgroud)

anu*_*shr 13

这个问题对我的设置非常具体(Nginx,PHP-FCGI,Symfony).

有一些问题导致了这个问题:

  1. symfony中不包括Content-Length也不Connection: close
  2. PHP-FCGI不支持该fastcgi_finish_request功能
  3. Nginx缓存来自PHP-FCGI的响应,因为Gzip已启用

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

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