Почему KernelEvents :: TERMINATE блокирует ответ пользователю?

В приложении Silex, работающем на HVVM, я настроил фиктивный прослушиватель событий в ядре TERMINATE:

$app['dispatcher']->addListener(
KernelEvents::TERMINATE,
function () use ($app) {
usleep(10000000);
$app['logger']->alert("I AM REGISTERED!");
}
);

Я ожидал, что мое приложение обработает ответ как можно быстрее в течение секунды, а через 10 секунд я ожидал сообщения "I AM REGISTERED" появляться в моем журнале.

Тем не менее, как ни странно, ответ отправляется после того, как событие было выполнено, то есть событие блокирует ответ на 10 секунд, и я вижу и ответ, и сообщение журнала одновременно.

Что здесь происходит?

Я нахожу странным, что в Application.php кажется, что send называется раньше terminate:

vendor/silex/silex/src/Silex/Application.php:

/**
* Handles the request and delivers the response.
*
* @param Request|null $request Request to process
*/
public function run(Request $request = null)
{
if (null === $request) {
$request = Request::createFromGlobals();
}

$response = $this->handle($request);
$response->send();
$this->terminate($request, $response);
}

1

Решение

symfony2 рассказывает о HttpKernel, какой звук также используется, он говорит:

Внутренне HttpKernel использует PHP fastcgi_finish_request
функция. Это означает, что на данный момент только сервер API PHP FPM
может отправить ответ клиенту, пока сервер PHP
Процесс все еще выполняет некоторые задачи. Со всеми другими серверными API,
слушатели kernel.terminate все еще выполняются, но ответ
не отправляется клиенту, пока все они не будут завершены.

А также fastcgi_finish_request является в настоящее время не поддерживается hhvm.

Следовательно, ответ не будет отправлен, пока не будут завершены все события.

1

Другие решения

  1. PHP не является асинхронным, поэтому, хотя обработка событий возможна с помощью обратных вызовов, как только событие сработает, ему будет выделен поток управления процессом.

  2. Фреймворки, как правило, задерживают отклик содержимого, чтобы быть последним предпринятым действием в случае, если должна произойти любая форма модификации заголовка.

Как вы упомянули, контент отправляется / отражается до TERMINATE событие произошло, но это еще не все.

Это зависит от того, как настроен ваш сервер. Если, например, у вас включен gzip в apache (очень часто), то апаш будет кэшировать весь контент до тех пор, пока PHP не завершит выполнение (а затем он отправит gzip и отправит его) Вы упомянули, что находитесь на HHVM, что также может быть проблемой — он может не очищать сам контент до тех пор, пока не завершится выполнение.

В любом случае, лучшее решение — это … ну … не спать. Я предполагаю, что вы спите, чтобы дать базе возможность перезаписаться на диск (хотя 10 секунд — это действительно долгое время, чтобы ждать этого). Если это не так, то найти достойное решение будет нелегко, пока мы не поймем Зачем вам нужно ждать так долго.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector