我正在运行一个基于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性能(=请求和响应之间的时间)时,我遇到了一个问题,我的代码运行了一堆代码,这些代码只是维护工作,并不是创建响应的真正必要:编写日志,添加响应的信息。请求统计信息等
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中实现吗?
答案 0 :(得分:1)
来自其他语言的这种说法很奇怪,但是对于PHP和Symfony来说都是很自然的。
PHP生命周期本身会初始化,并关闭每个请求的所有内容。这对安全性很有用(一个请求中的错误不会影响其他请求),但是对于速度而言却不是那么重要。
因此,同样适用于Symfony。一个请求进入,响应得到响应,一切都关闭(需要记录,刷新等)。 (旁注:SF能够处理多个请求-查看PHP-PM)
幸运的是,Symfony有一个kernel.terminate
事件,该事件使您可以在发送响应后运行代码。 http://symfony.com/doc/current/components/http_kernel.html#the-kernel-terminate-event
这对于某些东西非常有用,但仅适用于php-fpm。 一个很好的例子是电子邮件的内存假脱机:https://symfony.com/doc/current/email/spool.html
Symfony在发送响应后延迟发送电子邮件。
您可以为用例做同样的事情,只需要一个kernel.terminate
侦听器。您提到了某种请求状态...这将是创建和保存请求的好地方。
您还提到了日志记录:我不会对此太担心。在生产模式下,多亏了手指交叉的处理程序,因此只会记录错误。 https://symfony.com/doc/2.0/cookbook/logging/monolog.html#handlers-and-channels-writing-logs-to-different-locations
Monolog还带有一个用于在产品环境中进行记录的功能强大的内置处理程序:FingersCrossedHandler。它允许您将消息存储在缓冲区中,并仅在消息达到操作级别(标准版本提供的配置中为ERROR)时才将消息转发到另一个处理程序,以记录消息。
如果您认为登录文件太慢,也可以更改日志存储。我使用API(滚动条)记录错误,并且它根本不会影响性能-除非出现错误,否则我担心的最少是30毫秒左右的响应时间。
答案 1 :(得分:0)
让我们说您想在index.php
上运行2a
。您的要求是您不想等待index.php
完成后再发送响应。
您可以按照以下步骤进行操作:
$cmd="php index.php";
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
} else {
exec($cmd . " > /dev/null &");
}