如何在不同的请求中运行PHP后台操作/处理方法?

如何在不同的请求中运行PHP后台操作/处理方法?,php,symfony,Php,Symfony,我正在运行一个基于Symfony 2.8的web应用程序。基本上,对服务器的每个请求都分三步处理: 1. User/Browser sends request to the server 2. Server handles the request and performs any number of operations 3. Server sends back the result as response to the user 在测试WebApp性能(=请求和响应之间的时间)时,我遇

我正在运行一个基于
Symfony 2.8
的web应用程序。基本上,对服务器的每个请求都分三步处理:

 1. User/Browser sends request to the server
 2. Server handles the request and performs any number of operations
 3. Server sends back the result as response to the user
在测试WebApp性能(=请求和响应之间的时间)时,我遇到了一个问题,我的代码运行了一堆代码,这些代码只是维护,并不真正需要创建响应:编写日志,将请求的信息添加到stats中,等等

 2. Server handles the request and performs any number of operations
     2a. Necessary work to answer the request
     2b. Maintenance work 
如果代码跳过所有这些步骤,只运行创建响应所需的代码,那么用户将得到完全相同的响应

是否有可能将此工作移到后台/另一个请求,以将维护工作与“实际”工作分开,并更快地创建响应?

这在PHP中或者使用Symfony功能中是可能的吗

更准确地说:当然,“我的代码运行一堆只是维护的代码…”并不意味着每个请求需要30秒才能处理,删除维护代码可以减少几毫秒

我很清楚,删除这些东西不会提高性能,将一些维护代码保留在“真实”代码中比将所有内容移到“后台”要好得多


这是一个关于“如何将不需要处理请求的繁重维护工作转移到后台”的一般性问题。这在PHP中可能吗?

假设您想在
2a
运行
index.PHP
。您的要求是不希望在发送响应之前等待
index.php
完成

您可以按如下方式进行操作:

$cmd="php index.php";
if (substr(php_uname(), 0, 7) == "Windows"){
    pclose(popen("start /B ". $cmd, "r"));
} else {
    exec($cmd . " > /dev/null &");
}

来自其他语言,这可能会很奇怪,但对于PHP和Symfony来说都是很自然的

PHP生命周期本身会初始化并关闭每个请求的所有内容。这对安全性很好(一个请求中的错误不会影响其他请求),但对速度影响不大

因此,这同样适用于Symfony。一个请求进入,一个响应被提供,所有的东西都关闭(需要被记录、刷新等)。(旁注:Sf能够处理多个请求——看看PHP-PM)

幸运的是,Symfony有一个
内核。terminate
事件,允许您在发送响应后运行代码。

这对于某些内容非常有用,但仅适用于php fpm。 电子邮件的内存假脱机就是一个很好的例子:

Symfony在发送响应后延迟发送电子邮件

您可以对您的用例执行相同的操作,只需要一个
内核。终止
侦听器。你提到了某种请求统计。。。这将是一个伟大的地方来创建和保存

您还提到日志记录:我不会太担心它。在prod模式下,由于叉指处理器,只有错误才会被记录

Monolog还为登录prod环境提供了一个强大的内置处理程序:FingerScrossHandler。它允许您将消息存储在缓冲区中,并且仅当消息达到操作级别(标准版中提供的配置中出现错误)时,才通过将消息转发给另一个处理程序来记录消息


如果您认为记录到文件的速度太慢,还可以更改记录存储。我使用API(rollbar)记录错误,它根本不会影响性能-除非出现错误,在这种情况下,额外的~30ms响应时间是我最不担心的。

你不能控制symfony应该记录什么以及如何记录吗?非常感谢,
内核。termiate
在我的情况下是一个很好的解决方案!但是,这仅在使用
PHP-FPM
时有效。否则,
内核.terminate
处理程序中的代码仍将延迟响应。同时,我发现的另一个解决方案是这个捆绑包:如果您愿意将它与它自己的流程分离,您可以使用消息传递。rabbitmq使用者将是比异步进程更好的解决方案。