如何在 PHP 中的请求之间保留对象

发布于 2024-09-03 17:02:37 字数 703 浏览 11 评论 0原文

我过去一直使用rails、merb、django 和asp.net mvc 应用程序。他们的共同点(与问题相关)是他们都有设置框架的代码。这通常意味着创建持续存在的对象和状态,直到 Web 服务器被回收(例如设置路由或检查哪些控制器可用等)。

据我所知,PHP 更像是一个 CGI 脚本,每次运行时都会编译为一些字节码,并在请求之后被丢弃。当然,您可以拥有会话,以在同一用户的请求之间保留数据,并且正如我所看到的,有像 APC 这样的扩展,您可以使用它在服务器级别的请求之间保留对象。

我的问题是:如何创建一个像 Rails 等那样工作的 PHP 应用程序?我的意思是应用程序在第一个请求时设置框架,然后在第二个及以后的请求时使用已设置的对象。 mod_php 中是否有一些内置的缓存设施? (例如,存储已执行的 php 应用程序的编译字节码)或者使用 APC 或一些类似的扩展是解决此问题的唯一方法吗?你会怎么做?

谢谢。

编辑:替代问题:如果我创建一个大型 PHP 应用程序,它的设置时间非常长,但运行时间很短(如上面提到的框架),那么我应该如何“缓存”已经设置的内容(这可能意味着很多事情,除了数据库连接,因为为此你已经在 PHP 中拥有持久连接)。

为了证明较长的设置时间是合理的:如果我使用 PHP 反射来检查哪些对象可用并根据该对象设置运行时会怎样。进行大量反射通常很慢,但只需要做一次(并且仅在修改源代码时才重新评估)。

EDIT2:看来是APC了。很高兴知道它会自动缓存字节码。

I've been using rails, merb, django and asp.net mvc applications in the past. What they have common (that is relevant to the question) is that they have code that sets up the framework. This usually means creating objects and state that is persisted until the web server is recycled (like setting up routing, or checking which controllers are available, etc).

As far as I know PHP is more like a CGI script that gets compiled to some bytecode each time it's run, and after the request it's discarded. Of course you can have sessions, to persist data between requests from the same user, and as I see there are extensions like APC, with which you can persist objects between requests at the server level.

My question is: how can one create a PHP application that works like rails and such? I mean an application that on the first requests sets up the framework, then on the 2nd and later requests use the objects that are already set up. Is there some built in caching facility in mod_php? (for example that stores the compiled bytecode of the executed php applications) Or is using APC or some similar extensions the only way to solve this problem? How would you do it?

Thanks.

EDIT: Alternative question: if I create a large PHP application that has a very large set up time, but minor running time (like in the frameworks mentioned above) then how should I "cache" the things that are already set up (this might mean a lot of things, except for maybe the database connections, because for that you have persistent connections in PHP already).

To justify large set up time: what if I'm using PHP reflection to check what objects are available and set the runtime according to that. Doing a lot of reflection is usually slow, but one has to do it only once (and re-evaluate only if the source code is modified).

EDIT2: It seems it's APC then. The fact that it caches bytecode automatically is good to know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

站稳脚跟 2024-09-10 17:02:37

不确定 APC 是否是唯一的解决方案,但 APC 确实可以解决您的所有问题。

首先,您的脚本将使用 APC 编译一次,并将字节码存储在内存中。

如果您有一些需要很长时间才能设置的内容,您还可以将其作为用户数据缓存在 APC 中。例如,我一直这样做,

            $table = @apc_fetch(TABLE_KEY);

            if (!$table) {
                    $table = new Table(); // Take long time
                    apc_store(TABLE_KEY, $table);
            }

使用 APC,创建表的任务仅在每个服务器实例中执行一次。

Not sure if APC is the only solution but APC does take care of all your issues.

First, your script will be compiled once with APC and the bytecode is stored in memory.

If you have something taking long time to setup, you can also cache it in APC as user data. For example, I do this all the time,

            $table = @apc_fetch(TABLE_KEY);

            if (!$table) {
                    $table = new Table(); // Take long time
                    apc_store(TABLE_KEY, $table);
            }

With APC, the task of creating table is only performed once per server instance.

木緿 2024-09-10 17:02:37

PHP(以及 ruby​​)是解释性语言。也就是说,它们每次被请求时都会解析文件,我想你可以说它们被转换为伪字节代码。更“明显”的是,人们可以说 PHP 比 RoR 更像这样,但它们的行为方式相同。

在请求之间保留数据的功能是服务器的功能,而不是语言本身的功能。例如,您所说的 RoR 路由实际上是缓存的,但它缓存在服务器的本地内存中。它不是为了更快的读取而编译和存储的。服务器(我所说的服务器是指盒子和 Web 服务实例)重新启动,此信息消失了。您所说的“设置框架”仍然涉及解析框架中涉及的每个文件。 Rails 在请求期间一次又一次地解析每个文件,生产级功能实际上可能会将这些数据缓存在内存中,但在开发过程中肯定不会。我提到这一点的唯一原因是因为它说明它是服务器的功能而不是语言的功能。

要在 PHP 中实现相同的功能,您可以使用 Zend Server。据我所知,这是唯一一个在被告知时会“编译”并使用字节码的 PHP 解释器。否则,您需要找到一种方法来存储您想要在请求中保留的数据。正如您提到的,APC 是一项非常强大的功能,更分布式的功能是 Memcached,当然还有更持久的形式,例如磁盘和磁盘。 sql。

我很想知道您为什么喜欢这个特殊功能。您是否注意到这样做可以“解决”性能问题?

PHP (and ruby for that matter) are interpretive languages. That is they parse the files each time they are requested and I suppose you could say are converted to a pseudo byte code. It is more 'apparent' one could say that PHP is more like this than say RoR but they both behave the same way.

The feature of persisting data between requests is a feature of the server not of the language itself. For example, the RoR routing you speak of is in fact cached but that's cached in the server's local memory. It isn't compiled and stored for faster readins. The server (and by server I mean both the box & the web service instances) restarts this information is gone. The 'setting up the framework' you speak of still involves parsing EACH file involved in the framework. Rails parses each file during the request again and again, the production level features may in fact cache this data in memory but certainly in development it does not. The only reason I mention that is because it illustrates that it's a feature of the server not the language.

To achieve the same thing in PHP you could use Zend Server. As far as I know this is the only PHP interpreter that will 'compile' and use byte code when told to. Otherwise you'll need to find a way to store the data you want to persist over requests. APC as you mentioned is a very powerful feature, a more distributed one is Memcached and then of course there's more persistent forms like disc & sql.

I am interested in knowing why you'd like this particular feature. Are you noticing performance issues that would be 'solved' by doing this?

予囚 2024-09-10 17:02:37

我认为您做出了一些错误的概括。所有这些框架(例如:Rails )可以使用不同的配置运行。在某些情况下,会为每个请求创建一个流程。这显然会损害性能,但它表明这些框架不依赖于长时间运行的进程。如果需要,他们可以根据每个请求进行设置(重新解析配置文件、创建对象等)。

当然,mod_php(PHP 通常使用的方式)在 Web 服务器进程内运行,与 CGI 不同。所以我没有看到 CakePHP(例如)和 Rails 之间有什么本质上的不同。

我想也许你正在寻找类似 Python 的 WSGI 或 Ruby 的 Rack,但适用于 PHP。这指定了应用程序的接口(与语言的运行方式无关)。对于新请求,将创建应用程序对象的新实例。据我所知,PHP 不存在这种情况。

I think you're making some incorrect generalizations. All of those frameworks (ex: Rails) can be run with different configurations. Under some, a process is created for every request. This obviously hurts performance, but it shows that these frameworks don't rely on a long-running process. They can set things up (reparse config files, create objects, etc.) every request if needed.

Of course, mod_php (the way PHP is usually used) runs inside the web server process, unlike CGI. So I don't see anything fundamentally different between CakePHP (for example) and Rails.

I think perhaps you are looking for something like Python's WSGI or Ruby's Rack, but for PHP. This specifies an interface (independent of how the language is run) for an application. For a new request, a new instance of an application object is created. As far as I know, this does not exist for PHP.

就像说晚安 2024-09-10 17:02:37

开发人员运行 PHP 的最常见方式是使用 CGI 模块配置 Apache 作为 PHP 前面的适配器。当 Apache 收到 HTTP 请求时,验证路由是否与 PHP 文件/路径匹配,然后将执行委托给外部模块/程序,在本例中为 CGI 模块。然后将处理委托给 PHP 可执行文件。然后CGI启动一个新的PHP进程,沿着它的参数传递请求数据,然后PHP开始做这个工作,即打开PHP文件,读取它们,验证和解析,逐行执行指令,直到没有更多的指令。要解释的代码。然后产生的响应被发送回 Apache,最后其进程退出。内存返回给操作系统,然后对于每个请求,所有这些管道都会一遍又一遍地发生。

知道了这一点,我们注意到,如果在每个请求中启动和终止进程,则不会保留状态。例如,Node.js 的工作原理是启动单个线程、读取 .js 文件、解析它、对其进行一次优化,然后保持自身在内存中运行。没有进程结束和启动(除非崩溃)。

我不知道为什么 PHP/语言的开发人员决定在很长一段时间内遵循这种模块化方法,他们花了很多精力来优化这种架构(所有这些管道都非常快),但我知道有些公司采用了不同的解决方案,如 Facebook、Zend。

顺便说一句,作为一名高级工程师,我的建议是:保持简单,尽管使用了语言/堆栈,但只需应用每个人都会做的简单解决方案。将应用程序状态存储在专用空间中,例如Redis缓存、MySQL DB等。这是解决状态管理服务器应用程序的更常见的解决方案。应用程序不必依赖于其内存空间中的保存数据/状态。它必须存储在外部,并在每个请求中检索。这给我们带来了几个好处,其中包括所有计算机程序中最重要的一个:在并行运行的多个进程上共享数据。该功能的名称是:可扩展性。编写无状态应用程序

The most common way developers runs PHP is by configuring Apache with CGI module as an adapter in front of PHP. When Apache receives HTTP requests, verifies if a route matches to a PHP file/path, then it delegates the execution to an external module/program, in this case, the CGI module. Which will then delegate the processing to the PHP executable. A new PHP process is then started by CGI, passing request data along its parameters, and then PHP starts doing this job, which is to open PHP files, read them, validating and parsing, executing instructions line by line, until there are no more code to interpret. The response produced then is sent back to Apache and finally its process exits. Memory is returned back to OS, and then all of this pipeline happens over and over again, for every request.

Knowing this, we notice that if a process is started and terminated in every request, the state is not being preserved. Node.js for example, works by starting a single thread, read .js files, parses it, optimize it all once, and keeps itself running in memory. There is no process ending and starting (except when it crashes).

I dont know why the developers of the PHP/ Language have decided to follow this modularized approach for such a long time, they spent much effort in optimizing this architecture (it's very fast all this pipeline), but I know some companies evolved with different solutions, like Facebook, Zend.

By the way, my advice as a Senior Engineer is: Keep it simple, just apply a simple solution that everyone does, despite language/stack being used. Store application state in a dedicated space, like Redis cache, MySQL DB, etc. It's the more common solution to address the state management server applications. Applications doesnt have to depend on hold data/state in his memory space. It must be stored outside, and retrieved in every request. This brings us several benefits, including the most important in all computer programs: to share data on multiple processes running in parallel. The name of this feature is: Scalability. Write stateless applications

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文