PHP 架构:我该怎么做?
我需要一些帮助来理解 PHP 的内部工作原理。
还记得吗,在过去,我们曾经编写 TSR(终止并保持驻留)例程(Windows 之前的时代)?一旦该程序被执行,它将保留在内存中,并且可以通过某些热键(alt-或ctrl-组合键)重新执行。
我想在网络服务器/应用程序中使用类似的概念。比如说,我有 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 中的函数{如Generate_City_Combo()、Check_Permission()或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 内部工作原理的地方或书籍吗?
提前致谢。
I need some help understanding internal workings of PHP.
Remember, in old days, we used to write TSR (Terminate and stay resident) routines (Pre-windows era)? Once that program is executed, it will stay in memory and can be re-executed by some hot-key (alt- or ctrl- key combination).
I want to use similar concept in web server/applications. Say, I have common_functions.php which consists of common functions (like Generate_City_Combo(), or Check_Permission() or Generate_User_Permission_list() or like) to all the web applications running on that apache/php server.
In all the modules or applications php files, I can write:
require_once(common_functions.php) ;
which will include that common file in all the modules and applications and works fine.
My question is: How does php handle this internally?
Say I have:
Two applications AppOne and AppTwo.
AppOne has two menu options AppOne_Menu_PQR and AppOne_Menu_XYZ
AppTwo has two menu options AppTwo_Menu_ABC and APPTwo_Menu_DEF
All of these four menu items call functions { like Generate_City_Combo(), or Check_Permission() or Generate_User_Permission_list() } from common_functions.php
Now consider following scenarios:
A) User XXX logs in and clicks on AppOne_Menu_PQR from his personalized Dashboard then s/he follows through all the screens and instructions. This is a series of 8-10 page requests (screens) and it is interactive. After this is over, user XXX clicks on AppTwo_Menu_DEF from his personalized Dashboard and again like earlier s/he follows through all the screens and instructions (about 8-10 pages/screens). Then User XXX Logs off.
B) User XXX logs in and does whatever mentioned in scenario A. At the same time, user YYY also logs in (from some other client machine) and does similar things mentioned in scenario A.
For scenario A, it is same session. For Scenario B, there are two different sessions.
Assume that all the menu options call Generate_User_Permission_list() and Generate_Footer() or many menu options call Generate_City_Combo().
So how many times will PHP execute/include common_functions.php per page request? per session? or per PHP startup/shutdown? My understanding is common_functions.php will be executed once EVERY page request/cycle/load/screen, right? Basically once for each and every interaction.
Remember functions like Generate_City_Combo() or Generate_Footer() produces same output or does same thing irrespective of who or when is calling.
I would like to restrict this to once per Application startup and shutdown.
These are just examples. My actual problem is much more complex and involved. In my applications, I would like to call Application_Startup() routines just once which will create ideal environment (like all lookup and reference data structures, Read-Only-Data, Security-Matrix, Menu-options, context sensitive business execution logic etc..). After that all the requests coming to server need not spend any time or resources to create environment but can instantly refer "already-created-environment".
Is this something feasible in PHP? How? Could you point me to someplace or some books which explains internal working of PHP?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
PHP 在完全独立的执行框架中处理每个 HTTP 请求 - 没有运行的持久进程来为所有请求提供服务。 (您的网络服务器正在运行,但每次加载 PHP 页面时,都会调用 PHP 解释器的单独实例。)
如果生成所需的持久区域所需的时间很长,您可能希望考虑缓存输出从磁盘上的这些脚本中加载缓存版本(如果可用)(并且不是过时的)。
PHP processes each HTTP request in a completely separate frame of execution - there is no persistent process running to service them all. (Your webserver is running, but each time it loads a PHP page, a separate instance of the PHP interpreter is invoked.)
If the time it takes for your desired persistent areas to be generated is significant, you may wish to consider caching the output from those scripts on disk and loading the cached version first if it is available (and not out of date).
我想说你可能过早地优化了,但还是有希望的。
您经常需要在内存中保存已编译代码的多个副本,因为您希望每个请求都具有稳定性;您不希望单独的请求在同一内存空间中运行并冒竞争条件或数据损坏的风险!
也就是说,有无数 PHP 加速器 可以预编译 PHP 代码,大大加快 include 和 require 调用的速度。
I would say that you are likely prematurely optimizing, but there is hope.
You very frequently want multiple copies of your compiled code in memory since you want stability per request; you don't want separate requests operating in the same memory space and running the risk of race conditions or data corruption!
That said, there are numerous PHP Accelerators out there that will pre-compile PHP code, greatly speeding up include and require calls.
PHP(几乎在所有情况下)都是面向页面的。没有 Application_Startup() 可以跨 HTTP 请求维护状态。
有时您可以通过从数据库或 $_SESSION 加载/卸载序列化数据来模拟这一点,但会产生开销。此外,在其他情况下,memcached 服务器也可以对此进行优化,但您通常不能将其与典型的虚拟主机服务,如 cPanel。
如果我必须构建像您所说的那样的应用程序,我会将用户的选择序列化到会话中,然后将会话之间需要保留的任何内容保存在数据库中。
PHP 有几个 ORM 模块,例如 Doctrine ,它们简化了对象序列化到数据库。
PHP(in almost all cases) is page oriented. There is no Application_Startup() that will maintain a state across HTTP requests.
You can sometimes emulate this by loading/unloading serialized data from a database or $_SESSION, but there is overhead involved. Also, there are other cases where a memcached server can optimize this as well, but you typically can't use those with you typical virtual hosting services like cPanel.
If I had to build an app like you are talking about I would serialize the users choices into the session, and then save whatever needs to persist between sessions in a database.
There are several ORM modules for PHP like Doctrine which simplify object serialization to a database.
我在这里进行死灵术,但随着 PThread 的出现,似乎有可能朝着实际解决方案的方向前进,而不仅仅是不得不说,实际上,“不,你可以不要用 PHP 这样做。”
人们基本上可以用 PHP 创建自己的多线程 Web 服务器,只需使用 CLI 工具、socket_* 函数和 PThreads。只需侦听端口 80,将请求添加到请求队列,然后启动一定数量的工作线程来处理该队列。
可以根据请求队列长度和操作系统的运行队列长度来管理工作线程的数量。每隔几秒,主线程就会通过一个函数来管理工作池的大小。如果 Web 请求队列长度大于操作系统运行队列长度的某个常量倍,并且工作线程数小于配置的最大值,则它可以实例化另一个工作线程。如果 Web 请求队列长度小于其他某个(较低)常量乘以操作系统的运行队列长度,并且工作线程数量大于配置的最小值,则它可以告诉其中一个工作线程在完成当前请求时终止。然后可以调整常量和配置值以最大化服务器的所有吞吐量。类似的事情。
您必须自己完成所有 uri 解析,并且必须自己拼凑 HTTP 响应等,但工作线程可以实例化扩展 Threaded 的对象,或者重用以前实例化的 Threaded 对象。
瞧 - PHP TomCat。
I'm necromancing, here, but with the advent of PThread, it seems like there may be the possibility of a stab in the direction of an actual solution for this, rather than just having to say, in effect, "No, you can't do that with PHP."
A person could basically create their own multi-threaded web server in PHP, just with the CLI tools, the socket_* functions and PThreads. Just listen on port 80, add requests to a request queue, and launch some number of worker threads to process the queue.
The number of workers could be managed based on the request queue length and the operating system's run queue length. Every few seconds, the main thread could pass through a function to manage the size of the worker pool. If the web request queue length was greater than some constant times the operating system's run queue length and the number of workers was less than a configured maximum, it could instantiate another worker thread. If the web request queue length was less than some other (lower) constant times the OS's run queue length and the number of workers was greater than a configured minimum, it could tell one of the worker threads to die when it finishes its current request. The constants and configured values could then be tuned to maximize over all throughput for the server. Something like that.
You'd have to do all your own uri parsing, and you'd have to piece together the HTTP response yourself, etc., but the worker threads could instantiate objects that extend Threaded, or reuse previously instantiated Threaded objects.
Voila - PHP TomCat.