Single Point of Entry Apps.

php.internals

Michael Morris

10 years ago
Something I was reminded of during the discussion of replacing pear with composer that I thought was worthy of it's own thread. Most PHP apps I've seen that use composer are single point of entry apps - that is there's one front controller, usually index.php, and .htaccess rules are put in place that route all requests to that file. These apps then go through the process of initializing themselves and sometimes there are thousands of lines of code that get parsed through before the app is in ready state, the router finally loaded and a decision is made concerning the user's request. This is extremely inefficient What can be done in PHP core to more effectively embrace this paradigm without disturbing the current one? That's what this thread is to discuss. Here's my stab at it. Create an .htaccess directive that allows a php file to be a directory handler. When that directive is set the webserver will pass any non-existent file request to PHP (in effect becoming a one line replacement for a very common usage of mod_rewrite). When this directive is used two statements will be looked for by the runtime - first a ready statement (not necessarily named "ready"). When it is reached PHP will save the application state, clone it and continue working from the clone. On all all subsequent requests to the directory PHP will start by creating a new clone and working from there. The second statement instructs PHP to drop the saved state and load a new one starting with the next request (graceful) or to kill any concurrent workers (panic) This isn't the same as opcode caching - this would be caching of the entire application state including any data harvested from config file reads or database calls. It is possible to create this setup now using some PHP worker process trickery, but it isn't easy. Again, the above may not be a possible solution - but there's got to be a better way than the current approach which amounts to installing the application on every single request. Thank you all for your time.

Christoph Becker

10 years ago
On 05.09.2016 at 18:03, Michael Morris wrote:
> Something I was reminded of during the discussion of replacing pear with > composer that I thought was worthy of it's own thread. Most PHP apps I've > seen that use composer are > single point of entry apps - that is there's one front controller, usually > index.php, and .htaccess rules are put in place that route all requests to > that file. > > These apps then go through the process of initializing themselves and > sometimes there are thousands of lines of code that get parsed through > before the app is in ready state, the router finally loaded and a decision > is made concerning the user's request. > > This is extremely inefficient > > What can be done in PHP core to more effectively embrace this paradigm > without disturbing the current one? That's what this thread is to > discuss. Here's my stab at it. > > Create an .htaccess directive that allows a php file to be a directory > handler. When that directive is set the webserver will pass any > non-existent file request to PHP (in effect becoming a one line replacement > for a very common usage of mod_rewrite). > > When this directive is used two statements will be looked for by the > runtime - first a ready statement (not necessarily named "ready"). When it > is reached PHP will save the application state, clone it and continue > working from the clone. On all all subsequent requests to the directory PHP > will start by creating a new clone and working from there. > > The second statement instructs PHP to drop the saved state and load a new > one starting with the next request (graceful) or to kill any concurrent > workers (panic) > > This isn't the same as opcode caching - this would be caching of the entire > application state including any data harvested from config file reads or > database calls. > > It is possible to create this setup now using some PHP worker process > trickery, but it isn't easy. > > Again, the above may not be a possible solution - but there's got to be a > better way than the current approach which amounts to installing the > application on every single request. > > Thank you all for your time.
Not long ago (something like) this has already been proposed, see <http://news.php.net/php.internals/92249>ff.
-- Christoph M. Becker

Andrew Faulds

10 years ago
Hi Michael, Have you looked into PHP application servers, where the PHP code itself acts as the web (or FastCGI) server, and so can keep the whole framework etc. initialised in memory between requests? This is how other (non-PHP) web stacks avoid “installing the application on every single request”, and it can also be applied to PHP, it's just not very common. One example is Aerys (https://github.com/amphp/aerys), but it's hardly the first or the last example of this approach. Thanks.
-- Andrea Faulds https://ajf.me/

Michael Morris

9 years ago
On Mon, Sep 5, 2016 at 1:47 PM, Andrea Faulds <ajf@ajf.me> wrote:
> Hi Michael, > > Have you looked into PHP application servers, where the PHP code itself > acts as the web (or FastCGI) server, and so can keep the whole framework > etc. initialised in memory between requests? >
I have - it's what I was referring to when I mentioned PHP worker process trickery. I know it can be done, but it isn't straightforward and it can't be quickly applied to existing applications like Wordpress or Drupal.
> > This is how other (non-PHP) web stacks avoid “installing the application > on every single request”, and it can also be applied to PHP, it's just not > very common. >
I know. What I'm wondering though is, could there be a way to do this on the PHP engine level that would avoid massive rewrites of existing PHP code. Here's my current draft of a way to implement this using two statements. require_bootstrap( [FILE] ); This statement loads and executes the code in question just as require does. It saves the execution state before moving to the next code line after this statement is called. If called without a file it saves the execution state immediately. The saved execution state is hostname aware for sites that use a multisite configuration. So if the statement is reached from www.onesite.com/index.php and from www.twosite.com/index.php two different bootstraps will be created. This is done on the assumption that the booting process is going to make one or more decisions based on the hostname. Drupal loads entirely different setting files, module lists, uses a different Dependency Injector, all according to the hostname. unload_bootstrap( [PATH] ); This unloads the bootstrap associated with the webpath given. If no argument is given the current bootstrap image is dropped. Question - should passing boolean TRUE unload all the bootstraps at once, or should that be it's own function, or is it necessary? Note that bootstraps will be unloaded automatically if the opcode cache for the associated files changes. Thoughts, suggestions, questions, complains, or flames?

Daniel Morris

9 years ago
On Mon, 5 Sep 2016, at 06:47 PM, Andrea Faulds wrote:
> Hi Michael, > > Have you looked into PHP application servers, where the PHP code itself > acts as the web (or FastCGI) server, and so can keep the whole framework > etc. initialised in memory between requests? > > This is how other (non-PHP) web stacks avoid “installing the application > on every single request”, and it can also be applied to PHP, it's just > not very common. > > One example is Aerys (https://github.com/amphp/aerys), but it's hardly > the first or the last example of this approach. > > Thanks.
I'm sure I remember reading somewhere that fabpot was working on one in Golang? Something similar to Unicorn or Puma from the Ruby ecosystem would be a boon.
-- Daniel Morris daniel@honestempire.com