Подтвердить что ты не робот

Ответ возвращается только после события kernel.terminate

Мое понимание kernel.terminate заключается в том, что он запускается после того, как ответ был возвращен клиенту.

В моем жестком тестировании это, похоже, не так. Если я положил sleep(10) в функцию, вызывающую kernel.terminate. браузер также ждет 10 секунд. Обработка, по-видимому, происходит до отправки ответа.

У меня есть следующее в config:

calendar:
    class: Acme\CalendarBundle\Service\CalendarService
    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";
    }
}

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);
4b9b3361

Ответ 1

Этот вопрос оказался очень специфичным для моей установки (Nginx, PHP-FCGI, Symfony).

В игре было несколько проблем:

  • Symfony не включает заголовок Content-Length и Connection: close
  • PHP-FCGI не поддерживает функцию fastcgi_finish_request
  • Nginx буферизует ответ от PHP-FCGI, потому что Gzip включен

Решением было перейти от PHP-FCGI к PHP-FPM, чтобы получить поддержку fastcgi_finish_request. Symfony внутренне вызывает это перед выполнением логики завершения ядра, тем самым окончательно закрывая соединение.

Еще один способ решить это - отключить Gzip на Nginx, но для меня это был не вариант.