Download the PHP package jeremiah-shaulov/php-web-node without Composer

On this page you can find all versions of the php package jeremiah-shaulov/php-web-node. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package php-web-node

php-web-node

PhpWebNode is PHP-FPM implementation written in PHP that allows to preserve resources (global variables) between requests, so database connections pool is possible. Applications based on this library can be used instead of PHP-FPM. PhpWebNode acts like FastCGI server, to which web server (like Apache) will send HTTP requests. It will spawn child processes that will handle the requests synchronously. Several (up to 'pm.max_children') children will run in parallel, and each child will sequentially process incoming requests, preserving global (and static) variables.

How fast is php-web-node

It's written in PHP, so i expected that my application will slow down a little comparing to PHP-FPM. I was surprised that the application became a little faster. Actually php-web-node removes need to reinitialize resources, and reconnect to database.

What's supported

Most of PHP features that i know, except $_SESSION are supported. Most existing PHP scripts will work as with PHP-FPM, except principal distinction explained below, in "Step 3. Update PHP scripts".

PhpWebNode implements complete FastCGI protocol, including connection multiplexing, however as far as i know, currently none of popular web servers support this feature. More info.

Installation

Create a directory for your application, cd to it, and issue:

How to use php-web-node

To use php-web-node we need to pass 3 steps:

  1. Create master application
  2. Set up web server to use our application
  3. Update PHP scripts that we want to serve with php-web-node

Step 1. Create master application

We need a master application that will work as PHP-FPM service. Let's call it server.php:

The Server constructor takes array with configuration parameters. Their meaning is the same as in PHP-FPM, see here. Only parameters shown in the above example are supported.

Change johnny to your user name, or create dedicated user to run the application from it.

Now we need to start this script from console.

This script requires superuser rights, because it's going to create 'listen' socket, and it's parent directories. Then it switches user to one specified in the given configuration.

If we want to daemonize this service, we can either implement daemonization in the script, or we can use external software. For example in Ubuntu we can:

Step 2. Set up web server

If you have a web server like Apache or Nginx that is already configured to work with PHP-FPM, you only need to change the socket node name (or port) to that used in our server.php. In the example above it's /run/php-web-node/main.sock. Here's the simplest Apache example:

The DocumentRoot directory must exist, so create /var/www/wntest.com, or different directory on your choice, and put some test file in it, like index.php. Later you will be able to access it through ServerName URL. In example above, it's wntest.com, so the full URL will be http://wntest.com/index.php, or maybe http://wntest.com/. Also include wntest.com in your /etc/hosts file, like:

Step 3. Update PHP scripts

There's important difference between PHP-FPM and php-web-node. Let's say we have such index.php script:

If we'll serve this script with PHP-FPM, it will always show "Request 1", and process Id can change from request to request. From bunch of requests a percent of them will show the same process Id, because each child process (by default) processes many incoming requests.

If we'll serve it with php-web-node, we'll see that $n_request is incrementing. Probably you will see the same process Id, because your server can handle all the requests that come when you refresh the page with 1 child process. But there can be up to 'pm.max_children' (2 in the above example) processes, and request counter will increment in each child process independently.

Child process executes require 'index.php' each request within the same environment. This puts limitations on what index.php can do. For example:

To run this new script, you need to stop the server.php application, and rerun it again. This new script does the same thing, but it declares a function in global namespace. Doing require 'index.php' second time will give error:

There are 2 solutions to this problem.

  1. Put all functions and classes to external files, and require_once them.
  2. Use PhpWebNode\set_request_handler()

If we call PhpWebNode\set_request_handler() giving it a filename (usually __FILE__), requests to this file will be processed by calling specified callback function, and require for this file will not happen.

If you'll execute the above script from PHP-FPM, it will behave the same, because php-web-node determines that its not running from PhpWebNode\Server class, and executes the given callback function immediately.

Another important difference between php-web-node and PHP-FPM is that with php-web-node you cannot use built-in functions like header(), setcookie(), etc. Instead you need to use corresponding functions from PhpWebNode namespace: PhpWebNode\header(), PhpWebNode\setcookie(), etc.

Understanding the master application

The master application configures and starts the FastCGI server. Also it can perform another operations, but it's important to understand, that no blocking system calls must be executed from it, because blocking calls, like connecting to database, will pause handling incoming HTTP requests. The following master application is alright, it only performs nonblocking operations.

The $server->serve() function starts the server main loop, that runs forever, so this function doesn't return or throw exceptions.

This application prints each 6 sec (10 times a minute) how many requests were completed, and average request time. This time is measured since a child process took a request job, and till a complete response was received from the child. Real request time is longer.

Process pools

As we already mentioned, php-web-node manages child processes just like PHP-FPM, and each child process has it's own persistant resources. An example of resource is a database connection. So a PDO object stored in a global variable will not be reinitialized. If we set 'pm.max_children' to 10, we will get database connections pool with up to 10 slots.

What if we want that half of HTTP requests connect to one database, and a half to another? By default HTTP requests will be directed to random child processes, so each child will sometimes process requests that connect to database A, and sometimes to database B. So we will get 20 persistent connections from 10 child processes to 2 database servers.

PhpWebNode allows us to examine each incoming HTTP request in master application before it's directed to a child process, and the master application can choose to what group of children to direct it. Each group of child processes is called a process pool. We can have as many process pools as we want, and as many child processes in each pool as we want.

By default there's only 1 pool called '' (empty string). The 'pm.max_children' setting is maximal number of processes in each pool.

To catch and examine incoming HTTP requests we can set $server->onrequest() callback.

$onrequest_func callback receives a Request object, that has the following fields:

$onrequest_func allows you to decide to which pool to forward the incoming HTTP request by returning pool Id or name (string).

It's important to return only fixed number of value alternatives. In the example above we return 2 alternatives: 'A' and 'B', so we will get 2 pools with 5 ('pm.max_children') processes in each pool. If you cease returning some value from $onrequest_func callback, the corresponding pool will be eventually freed.

Child process can check it's pool Id by calling PhpWebNode\get_pool_id().

Another thing that $onrequest_func callback can do, is throwing exception to cancel the request without forwarding it to a child process.

PHP MySQL connections pool implementation

As we saw above, process pool can act like database connections pool.

Please, keep in mind, that there's no way in PHP to reset a MySQL connection using mysql_reset_connection(), at least i'm not aware of such. Therefore in the beginning of each request we'll need to clean up what we can, and we can rollback ongoing transaction if it was not committed by previous request.

Also you need to know that depending on what queries you execute, memory consumption on MySQL end can decline with every query. Eventually this can make MySQL server unresponsive. So there's limit on how many times we can reuse our connection, and we need to reconnect periodically anyway. Even reusing 10 times each connection, will dramatically release network pressure in your system.

In my experiments, with PHP-FPM i saw 2500 open sockets all the time, where almost all of them were in TIME_WAIT state.

With php-web-node reusing each connection 10 times, this number reduced to 700.

Example of client script that implements DB connections pool:

And as usual, in master application we specify pool parameters:

The pool will have up to pm.max_children concurrent database connections. If one of them remains idle for more than pm.process_idle_timeout seconds, it will be closed. Each pm.max_requests requests child process will be retired, so we could set pm.max_requests to 10, and database connection would reconnect each 10 requests, but it's better to set pm.max_requests to a big value because this will save CPU spent on stopping child process, and forking it again.


All versions of php-web-node with dependencies

PHP Build Version
Package Version
Requires php Version >=7.4
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package jeremiah-shaulov/php-web-node contains the following files

Loading the files please wait ....