4

我需要一些帮助来理解 PHP 的内部工作原理。

还记得,在过去,我们曾经编写过 TSR(Terminate and stay resident)例程(Windows 之前的时代)吗?一旦执行该程序,它将保留在内存中,并且可以通过一些热键(alt-或 ctrl-组合键)重新执行。

我想在 Web 服务器/应用程序中使用类似的概念。比如说,我有 common_functions.php,它包含在该 apache/php 服务器上运行的所有 Web 应用程序的通用函数(如 Generate_City_Combo()、Check_Permission() 或 Generate_User_Permission_list() 等)。

在所有模块或应用程序的 php 文件中,我可以写:
require_once(common_functions.php) ;

这将在所有模块和应用程序中包含该公共文件并且工作正常。

我的问题是:php 如何在内部处理这个问题?
假设我有:两个应用程序 AppOne 和 AppTwo。
AppOne 有两个菜单选项 AppOne_Menu_PQR 和 AppOne_Menu_XYZ
AppTwo 有两个菜单选项 AppTwo_Menu_ABC 和 APPTwo_Menu_DEF

所有这四个菜单项都从 common_functions.php 调用函数 { like Generate_City_Combo(), or Check_Permission() or Generate_User_Permission_list() }

现在考虑以下场景: A) 用户 XXX 登录并从他的个性化仪表板中单击 AppOne_Menu_PQR,然后她/他按照所有屏幕和说明进行操作。这是一系列 8-10 个页面请求(屏幕),它是交互式的。在此结束后,用户 XXX 从他的个性化仪表板中单击 AppTwo_Menu_DEF,并再次像之前一样遵循所有屏幕和说明(大约 8-10 页/屏幕)。然后用户 XXX 注销。

B) 用户 XXX 登录并执行场景 A 中提到的任何操作。同时,用户 YYY 也登录(从其他客户端计算机)并执行场景 A 中提到的类似操作。

对于场景 A,它是同一个会话。对于场景 B,有两个不同的会话。

假设所有菜单选项调用 Generate_User_Permission_list() 和 Generate_Footer() 或许多菜单选项调用 Generate_City_Combo()。

那么 PHP 每个页面请求会执行多少次/包含 common_functions.php 呢?每个会话?还是每个 PHP 启动/关闭?我的理解是 common_functions.php 将在每个页面请求/周期/加载/屏幕上执行一次,对吗?基本上每次交互一次。

请记住,Generate_City_Combo() 或 Generate_Footer() 之类的函数会产生相同的输出或执行相同的操作,而不管调用者是谁或何时调用。

我想将其限制为每次应用程序启动和关闭一次。

这些只是例子。我的实际问题要复杂得多。在我的应用程序中,我想只调用一次 Application_Startup() 例程,这将创建理想的环境(如所有查找和引用数据结构、只读数据、安全矩阵、菜单选项、上下文相关的业务执行逻辑等。 .)。之后,所有到达服务器的请求不需要花费任何时间或资源来创建环境,而是可以立即引用“已经创建的环境”。

这在 PHP 中可行吗?如何?你能指出我解释PHP内部工作的某个地方或一些书籍吗?

提前致谢。

4

4 回答 4

2

PHP 在一个完全独立的执行框架中处理每个 HTTP 请求 - 没有持续运行的进程来为它们提供服务。(您的网络服务器正在运行,但每次加载 PHP 页面时,都会调用一个单独的 PHP 解释器实例。)

如果生成所需的持久区域所花费的时间很长,您可能希望考虑将这些脚本的输出缓存在磁盘上,如果缓存版本可用(并且没有过期),则首先加载缓存的版本。

于 2010-02-27T04:29:45.650 回答
1

PHP(几乎在所有情况下)都是面向页面的。没有 Application_Startup() 将跨 HTTP 请求维护状态。

您有时可以通过从数据库或 $_SESSION 加载/卸载序列化数据来模拟这一点,但会涉及开销。此外,在其他情况下,memcached服务器也可以对此进行优化,但您通常不能将它们与典型的虚拟主机服务(如 cPanel)一起使用。

如果我必须像您所说的那样构建一个应用程序,我会将用户选择序列化到会话中,然后将会话之间需要保留的任何内容保存在数据库中。

有几个用于 PHP 的 ORM 模块,例如Doctrine,它们简化了对数据库的对象序列化。

于 2010-02-27T04:32:46.940 回答
1

我会说你可能过早地优化,但有希望。

您经常需要在内存中保存多个已编译代码的副本,因为您希望每个请求都具有稳定性;您不希望单独的请求在同一内存空间中运行并冒着竞争条件或数据损坏的风险!

也就是说,有许多PHP加速器可以预编译 PHP 代码,从而大大加快 include 和 require 调用的速度。

于 2010-02-27T04:34:12.723 回答
0

我在这里是死灵法师,但是随着 PThread 的出现,似乎有可能朝着实际解决方案的方向迈进,而实际上不必说:“不,你可以不要用 PHP 那样做。”

一个人基本上可以在 PHP 中创建自己的多线程 Web 服务器,只需使用 CLI 工具、socket_* 函数和 PThreads。只需监听 80 端口,将请求添加到请求队列,然后启动一些工作线程来处理队列。

可以根据请求队列长度和操作系统的运行队列长度来管理工作人员的数量。每隔几秒钟,主线程就会通过一个函数来管理工作池的大小。如果 Web 请求队列长度大于某个常数乘以操作系统的运行队列长度并且工作线程的数量小于配置的最大值,它可以实例化另一个工作线程。如果 Web 请求队列长度小于某个其他(较低)常数乘以操作系统的运行队列长度并且工作线程的数量大于配置的最小值,则它可以告诉其中一个工作线程在完成当前请求时死亡。然后可以调整常量和配置值以最大化服务器的所有吞吐量。类似的东西。

您必须自己进行所有 uri 解析,并且必须自己拼凑 HTTP 响应等,但工作线程可以实例化扩展 Threaded 的对象,或重用先前实例化的 Threaded 对象。

瞧 - PHP TomCat.

于 2014-10-06T19:52:28.127 回答