本文介绍了为什么KernelEvents :: TERMINATE阻止对用户的响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



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

我期待我的应用程序在一秒钟内尽可能快地呈现响应,10秒后我预期消息我注册出现在我的日志中。



但奇怪的是,事件发生后已被执行,意味着事件阻止10秒的响应,同时我同时看到响应和日志消息。



这里发生了什么? p>

我发现在Application.php中,在之前调用发送终止



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

  / ** 
*处理请求并提供响应。
*
* @param Request | null $ request请求处理
* /
public function run(Request $ request = null)
{
if (null === $ request){
$ request = Request :: createFromGlobals();
}

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


解决方案

  1. PHP不是异步的,所以通过使用回调来实现事件处理是可能的,一旦事件触发,流程的控制流就会专用于它。


  2. 框架往往会延迟内容回应成为最后采取的行动,以防任何形式的标题修改发生。


如上所述,在 TERMINATE 事件被触发之前,内容正在发送/回显,但这不是整个故事。



这取决于您的服务器的设置方式。例如,如果您在apache(非常常见)中启用了gzip,那么apache 将缓存所有内容,直到PHP完成执行(然后gzip并发送它)。你提到你在HHVM,这也可能是问题 - 它可能不会刷新内容,直到执行完成。



无论哪种方式,最好的解决方案是到...好...不睡觉我假设你正在睡觉,给数据库一个机会刷新磁盘(10秒是一个很长的时间等待,但是)。如果不是这样,那么找到一个体面的解决方案并不容易,直到我们可以理解为什么你需要等待那么久。


In a Silex application running on HVVM I have setup a dummy event listener on Kernel TERMINATE:

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

I was expecting my application to render the response as fast as possible within a second and after 10s I expected the message "I AM REGISTERED" to appear in my log.

Yet strangely the response is sent after the event has been executed, meaning the event blocks the response for 10s and I see both the response and the log message at the same time.

What is going on here?

I find it odd that in the Application.php, it appears that send is called before 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. PHP is not asynchronous, so while event handling is possible through use of callbacks, as soon as the event triggers, the control flow of the process will be dedicated to it.

  2. Frameworks tend to delay content response to be the last action taken, in case any form of header modification has to happen.

As you mentioned, the content is being sent/echoed before the TERMINATE event is fired, but that's not the whole story.

It depends on how your server is set up. If, for example, you have gzip enabled in apache (very common), then apache will cache all content until PHP has finished execution (and then it will gzip and send it). You mentioned that you're on HHVM, which could also be the problem - it might not flush the content itself until execution is complete.

Either way, the best solution is to... well... not sleep. I'm assuming that you're sleeping to give the database a chance to flush to disk (10 seconds is a really long time to wait for that, though). If that's not the case, then finding a decent solution won't be easy until we can understand why you need to wait that long.

这篇关于为什么KernelEvents :: TERMINATE阻止对用户的响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 08:51