For a recent project, I have a PHP script running as a CLI-based daemon. This daemon will be responsible for monitoring/controlling independent worker processes.
Periodically, users will issue requests to manage workers through a PHP web front-end (CLI daemon and front-end code are on the same physical server). The front-end will need to make method calls to the daemon.
I'm confused about how to handle these "remote" method calls. I thought that using a RPC protocol such as JSON-RPC over a standard UNIX or TCP socket would be the way to go, but every implementation of JSON-RPC, XML-RPC, SOAP, etc. for PHP seems to be tightly coupled to HTTP. Since I'm not communicating over the web, HTTP is completely unnecessary.
So, two questions:
Why are most of the PHP RPC packages coupled to HTTP?
What is the best way to handle method calls as described above?
Why are most of the PHP RPC packages coupled to HTTP?
This is easy. PHP is tailored for the web. It's rarer to write CLI applications in PHP.
Why are most of the PHP RPC packages coupled to HTTP?
It's more common to have PHP perform RPC on programs running in another language, such as Java, and there are good options there.
For a CLI PHP program, I'm not aware of any out-of-the-box solution. But it should be possible to implement a custom solution with UNIX sockets. See the sockets extension. Note that the nonexistence of multi-threading support in PHP may make this a bit more difficult (to handle multiple connections you'll have to fork or implement your own single-thread scheduler...)
You could still use HTTP and connect to localhost, that would not generate any network traffic. I don't think there is any real advantage to be gained by using sockets directly, however if you really want a different transport layer, you could use Ripcord (http://ripcord.googlecode.com/) which allows you to specify your own transport layer class. For full disclosure, I am the author of Ripcord, so I may be biased.
Related
For Java we have different Application servers like WebSphere and Web logic,
My Doubt is do we have any PHP Application servers?
Till now We are using Apache and Nginx web servers for PHP Web applications. How Application servers are useful to PHP?
Thanks
Ramu
With PHP-PM, RoadRunner, Swoole the label "app server" is arguable, but they all solve the most problematic part: the wasteful "process app reinit & cleanup on every request". And, in addition to removing the entire HTTP server → aux. process mgmt. → PHP script loading/processing detour from the pipeline (by having an integrated, in-process HTTP server + process management facilities), they also add varying levels/amounts of extra services to help building robust long-lived server-side apps in PHP.
Swoole is technically implemented as a PHP extension, but does much more than the usual ones. It launches worker processes on its own, and it's used like a framework: you'll write your event loop and pass control to Swoole. Your app will be hooked up to handle HTTP requests (or websocket events etc.), using their nonblocking async I/O (networking, filesystem, process mgmt.), plus various other handy services incl. coroutines, IPC, locking etc.). All the async., performance-critical I/O is dealt with in C, via a straightforward PHP API, including:
HTTP server and client
TCP/UDP server and client
Websocket server
Redis server
MySQL client
Filesystem I/O, IPC, process mgmt. etc.
https://scottaubrey.info/blog/2018-10-22-first-look-at-swoole/
It's basically Node.js for PHP
→ Unofficial extra docs (in addition to the official ones)
RoadRunner is a process manager server (written in Go). From their feature list:
PSR-7 HTTP server (file uploads, error handling, static files, hot reload, middlewares, event listeners)
HTTPS and HTTP/2 support (including HTTP/2 Push, H2C)
Fully customizable server, FastCGI support
Load balancer, process manager and task pipeline
Works over TCP, UNIX sockets and standard pipes
Automatic worker replacement and safe PHP process destruction
Worker lifecycle management (controller)
Very fast (~250k rpc calls per second on Ryzen 1700X using 16 threads)
Integrations with Symfony, Laravel, Slim, CakePHP, Zend Expressive
Automatic reloading on file changes
Works on Windows (Unix sockets (AF_UNIX) supported on Windows 10)
PHP-PM is another advanced PHP process manager (like RoadRunner), but also comes with an app (meta)framework, built on top of ReactPHP (another event-driven, async. I/O lib, similar to Swoole, but implemented in PHP, so inherently slower). This package covers most of the ground of the app-server chores (https://laravel-news.com/php-pm). Some of their listed features:
Integrated load balancer.
Hot-Code reload (when PHP files change).
Static file serving for easy development procedures.
Support for HttpKernel (Symfony/Laravel), Drupal (experimental), Zend (experimental).
Bonus: here's a nice, detailed performance test of various architecture alternatives (excluding Swoole) for long-lived sever-side PHP processes. For Swoole (compared to other frameworks, not other PHP process piping setups!), see this nice framework performance chart; it's pretty scary fast.
I was thinking of implementing real time chat using a PHP backend, but I ran across this comment on a site discussing comet:
My understanding is that PHP is a
terrible language for Comet, because
Comet requires you to keep a
persistent connection open to each
browser client. Using mod_php this
means tying up an Apache child
full-time for each client which
doesn’t scale at all. The people I
know doing Comet stuff are mostly
using Twisted Python which is designed
to handle hundreds or thousands of
simultaneous connections.
Is this true? Or is it something that can be configured around?
Agreeing/expanding what has already been said, I don't think FastCGI will solve the problem.
Apache
Each request into Apache will use one worker thread until the request completes, which may be a long time for COMET requests.
This article on Ajaxian mentions using COMET on Apache, and that it is difficult. The problem isn't specific to PHP, and applies to any back-end CGI module you may want to use on Apache.
The suggested solution was to use the 'event' MPM module which changes the way requests are dispatched to worker threads.
This MPM tries to fix
the 'keep alive problem' in HTTP.
After a client completes the first
request, the client can keep the
connection open, and send further
requests using the same socket. This
can save signifigant overhead in
creating TCP connections. However,
Apache traditionally keeps an entire
child process/thread waiting for data
from the client, which brings its own
disadvantages. To solve this problem,
this MPM uses a dedicated thread to
handle both the Listening sockets, and
all sockets that are in a Keep Alive
state.
Unfortunately, that doesn't work either, because it will only 'snooze' after a request is complete, waiting for a new request from the client.
PHP
Now, considering the other side of the problem, even if you resolve the issue with holding up one thread per comet request, you will still need one PHP thread per request - this is why FastCGI won't help.
You need something like Continuations which allow the comet requests to be resumed when the event they are triggered by is observed. AFAIK, this isn't something that's possible in PHP. I've only seen it in Java - see the Apache Tomcat server.
Edit:
There's an article here about using a load balancer (HAProxy) to allow you to run both an apache server and a comet-enabled server (e.g. jetty, tomcat for Java) on port 80 of the same server.
You could use Nginx and JavaScript to implement a Comet based chat system that is very scalable with little memory or CPU utilization.
I have a very simple example here that can get you started. It covers compiling Nginx with the NHPM module and includes code for simple publisher/subscriber roles in jQuery, PHP, and Bash.
http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/
PHP
I found this funny little screencasts explaining simple comet. As a side note I really think this is going to kill your server on any real load. When just having a couple of users, I would say to just go for this solution. This solution is really simple to implement(screencasts only takes 5 minutes of your time :)). But as I was telling previously I don't think it is good for a lot of concurrent users(Guess you should benchmark it ;)) because:
It uses file I/O which is much slower then just getting data from memory. Like for example the functions filemtime(),
Second, but I don't think least PHP does not a have a decent thread model. PHP was not designed for this anyway because of the share nothing model. Like the slides says "Shared data is pushed down to the data-store layer" like for example MySQL.
Alternatives
I really think you should try the alternatives if you want to do any comet/long polling. You could use many languages like for example:
Java/JVM: Jetty continuations.
Python: Dustin's slosh.
Erlang: Popular language for comet/etc.
Lua, Ruby, C, Perl just to name a few.
Just performing a simple google search, will show you a lot alternatives also PHP(which I think on any big load will kill your server).
mod_php is not the only way to use PHP. You can use fastcgi. PHP must be compiled with --enable-fastcgi.
PHP as FastCGI: http://www.fastcgi.com/drupal/node/5?q=node/10
You may also try https://github.com/reactphp/react
React is a low-level library for event-driven programming in PHP. At its core is an event loop, on top of which it provides low-level utilities, such as: Streams abstraction, async dns resolver, network client/server, http client/server, interaction with processes. Third-party libraries can use these components to create async network clients/servers and more.
The event loop is based on the reactor pattern (hence the name) and strongly inspired by libraries such as EventMachine (Ruby), Twisted (Python) and Node.js (V8).
The introductory example shows a simple HTTP server listening on port 1337:
<?php
$i = 0;
$app = function ($request, $response) use (&$i) {
$i++;
$text = "This is request number $i.\n";
$headers = array('Content-Type' => 'text/plain');
$response->writeHead(200, $headers);
$response->end($text);
};
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);
$http->on('request', $app);
$socket->listen(1337);
$loop->run();
I'm having a similar issue. One option I'm finding interesting is to use an existing Comet server, like cometd-java or cometd-python, as the core message hub. Your PHP code is then just a client to the Comet server -- it can post or read messages from channels, just like other clients.
There's an interesting code snippet linked here: http://morglog.org/?p=22=1 that implements part of this method (although there are bits of debug code spread around, too).
I'm current implementing a scalable PHP Comet server using socket functions. It is called 'phet' ( [ph]p com[et] )
Project page: http://github.com/Tim-Smart/phet
Free free to join in on development. I have currently managed to get most of the server logic done, just need to finish off the client side stuff.
EDIT: Recently added 'Multi-threading' capabilities using the pcntl_fork method :)
You'll have a hard time implementing comet in PHP, just because of it's inherent single-threaded-ness.
Check out Websync On-Demand - the service lets you integrate PHP via server-side publishing, offloading the heavy concurrent connection stuff, and will let you create a real-time chat app in no time.
A new module just came out for the nginx web server that'll allow Comet with any language, including PHP.
http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/
You will have to create your own server in PHP. Using Apache/mod_php or even fastcgi will not scale at all. A few years old, but can get you started:
PHP-Comet-Server:
http://sourceforge.net/projects/comet/
I think this is more an issue that having a lot of apache threads running all the time is a problem. That will existing with any language if it works via apache in the same way as PHP (usually) does.
I have been searching Google for a while, but the problem I am running into is I am not exactly sure what it is I need to be searching for. (Searching for PHP C++ communication doesn't seem to be what I need) I am basically developing a c++ plugin for a game server, and I would like to create a web interface that can pass/pull data to and from the C++ plugin. The game already uses an RCON port for remote administrative access, but I stumbled across a header for the Network interface they use, so I assume I could use this.
My problem is I am not very familiar with using sockets. I assume I will basically need to open a socket in C++ and leave it listening, and then in the PHP, connect to that socket, pass the data, and close it.
Here is the interface...
http://www.ampaste.net/m2f6b6dbc
I am mostly just going to be pulling information like current list of connected players, names, and scores. And passing commands to restart the server, shut it down, etc.
Any help would be great, thanks!
You could try Thrift. It was written by the engineers at Facebook, and it's now an Apache project.
Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml.
Link: http://incubator.apache.org/thrift/
In a nutshell it does exactly what you're trying to do. It makes it easy for different languages to communicate with each other. Rather than trying to come up with some socket based protocol for communication, you can call a function in PHP like this:
$game->getScores();
And it automatically plugs into a function named getScores in your C/C++ program. The only drawback is it can be a bit of a pain to configure correctly.
I'd dare to recommend to use some standard means of distributed components communication, for example, XML RPC. There are libraries for both PHP and C++: http://en.wikipedia.org/wiki/XML-RPC#Implementations
This approach will keep you from reinventing the wheel during communication protocol implementation, and will make further maintenance cheaper.
I assume I will basically need to open a socket in C++ and leave it listening
err, yes, that's the description I'd give to my 12 year-old daughter - but if you're going to have more than one client connecting its a bit more involved. Especially if you are bolting the code onto an existing server. So have a read of the socket programming FAQ.
You do need to define a protocol of how data will be represented when travelling across the socket. THere are lots of 'standard methods - but sometimes things like CORBA / SOAP etc can just be overkill and more effort than starting from scratch.
If you are bolting code ontp an existing server, life will be a lot simpler if you use the current socket and extend the protocol if necessary.
There are 3 models for writing a socket server - the code snippet you provided does not seem to include details of which you are currently working with:
forking server (may split threads rather than processes)
single-threaded server
socketless server
forking server
An instance of the server is started (call it p1), calling setsid()
p1 starts listening on the relevant socket
a client tries to connect
p1 forks to create p2
p2 then accepts the connection and starts conversing with the client
p1 continues to listen for further connections
p2 exits when the connection closes
There are variations of this - p2 may accept further connections, p1 might fork prior to a connection coming in)
single-threaded
An instance of the server is started, calling setsid()
it starts listening for a connection, and creates an array of the sockets in use (including the initial one)
socket_select() is used to identify activity from any of the sockets
when a client connects, the connection is accepted and added to an array of connections
whenever socket_select() returns activity on one of the sockets, the server generaets an appropriate response / closes the socket / binds the new connection
socketless server
some process (e.g. inetd) handles all the socket stuff
when a client connects, this other server starts an instance of your program and binds the socket I/O to the STDIN/STDOUT of your program
when your program exits, the other process closes the socket (if its still open) and handles the clean up (e.g. if it is implemented as a forking server, then the spawned process may end)
What it appears you want to google is C++ client / server. There are two approaches I could suggest here.
First, would be to make a very basic HTTP protocol server so that your php script can simply go to http://yourip/ and send your commands through the POST variables. You can find an example of a C++ Web Server at: https://stackoverflow.com/questions/175507/c-c-web-server-library
The second approach which allows a lot more flexibility is make up your own basic protocol and use PHP's SOCKETS to connect to the server and send commands. You can find an example of a C++ client / server application at http://www.codeproject.com/KB/IP/client_server_socket.aspx. Keep in mind, for the C++ end, you are only concerned about the Server part. You can find a basic PING client in PHP, using sockets, at the following URL: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=8&txtCodeId=1786. There are also classes out there to handle most of the protocol part, though I am not aware of any that work for both languages.
Please note I have not tested any of the codes I linked to. I simply found them on google.
A good place to start would be http://php.net/manual/en/book.sockets.php.
Basically, you're going to create another remote administration port and method for PHP to connect. Naturally, if your going to only be accepting web communication from one IP, that's a good way to secure it (check and allow access to only the one IP which will connect). However, you will need the C++ server to listen on a (secure?) port and have PHP connect to it (as long as host allows it).
So overall, if you already have a server running, this should be simple from the C++ side. All you need to do from the PHP side is really research connecting to different servers and passing information along (which PHP is more than capable of doing efficiently)
But, this is obviously an alternative to the poster up 2. I personally enjoy (in many cases) "reinventing the wheel" so to speak as to be able to manage my own work. But of course, that is not always efficient by cost or otherwise.
Good luck!
How do I implement a PHP Socket Server, I am using PHP5.
Is there a ready made framework already available for me to use instead of going into the nitty gritties of the implementation details?
Basically I want to serve Flash clients using this Socket Server and this would be running in an Apache Environment.
This is the first time I am treading into PHP territory so consider me a noob.
Have a look at Aleksey Zapparov's PHP Socket server
http://www.phpclasses.org/browse/package/5758.html
Its very simple to hange your own code off it. But be warned that you should be careful about your memory management. If you're writing a very complex OO app, then you should definitely install the ciercular reference checking garbage collector. And, since it use socket_select() you don't want ti to be hanging around too long witing for your code to do something.
Alternatively (if you are running on anything other than a Microsoft platform) it may be simpler to hang the php process off [x]inetd and just use stdio for communications.
HTH
C.
Check out Zend_AMF (emphasis mine)
Zend_Amf provides support for Adobe's » Action Message Format (AMF), to allow communication between Adobe's » Flash Player and PHP. Specifically, it provides a gateway server implementation for handling requests sent from the Flash Player to the server and mapping these requests to object and class methods and arbitrary callbacks.
http://framework.zend.com/download/amf
http://fritzthomas.com/php/zend-framework/329-zend_amf-update-and-examples/
and AMFPHP as an alternative.
Also, check out PHP Socket's API and check out this IBM Article about Memory Management with PHP.
Edit
This is not server push though. PHP is not well suited for long running processes. If you want a push implementation, have a look at Comet technologies.
I was thinking of implementing real time chat using a PHP backend, but I ran across this comment on a site discussing comet:
My understanding is that PHP is a
terrible language for Comet, because
Comet requires you to keep a
persistent connection open to each
browser client. Using mod_php this
means tying up an Apache child
full-time for each client which
doesn’t scale at all. The people I
know doing Comet stuff are mostly
using Twisted Python which is designed
to handle hundreds or thousands of
simultaneous connections.
Is this true? Or is it something that can be configured around?
Agreeing/expanding what has already been said, I don't think FastCGI will solve the problem.
Apache
Each request into Apache will use one worker thread until the request completes, which may be a long time for COMET requests.
This article on Ajaxian mentions using COMET on Apache, and that it is difficult. The problem isn't specific to PHP, and applies to any back-end CGI module you may want to use on Apache.
The suggested solution was to use the 'event' MPM module which changes the way requests are dispatched to worker threads.
This MPM tries to fix
the 'keep alive problem' in HTTP.
After a client completes the first
request, the client can keep the
connection open, and send further
requests using the same socket. This
can save signifigant overhead in
creating TCP connections. However,
Apache traditionally keeps an entire
child process/thread waiting for data
from the client, which brings its own
disadvantages. To solve this problem,
this MPM uses a dedicated thread to
handle both the Listening sockets, and
all sockets that are in a Keep Alive
state.
Unfortunately, that doesn't work either, because it will only 'snooze' after a request is complete, waiting for a new request from the client.
PHP
Now, considering the other side of the problem, even if you resolve the issue with holding up one thread per comet request, you will still need one PHP thread per request - this is why FastCGI won't help.
You need something like Continuations which allow the comet requests to be resumed when the event they are triggered by is observed. AFAIK, this isn't something that's possible in PHP. I've only seen it in Java - see the Apache Tomcat server.
Edit:
There's an article here about using a load balancer (HAProxy) to allow you to run both an apache server and a comet-enabled server (e.g. jetty, tomcat for Java) on port 80 of the same server.
You could use Nginx and JavaScript to implement a Comet based chat system that is very scalable with little memory or CPU utilization.
I have a very simple example here that can get you started. It covers compiling Nginx with the NHPM module and includes code for simple publisher/subscriber roles in jQuery, PHP, and Bash.
http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/
PHP
I found this funny little screencasts explaining simple comet. As a side note I really think this is going to kill your server on any real load. When just having a couple of users, I would say to just go for this solution. This solution is really simple to implement(screencasts only takes 5 minutes of your time :)). But as I was telling previously I don't think it is good for a lot of concurrent users(Guess you should benchmark it ;)) because:
It uses file I/O which is much slower then just getting data from memory. Like for example the functions filemtime(),
Second, but I don't think least PHP does not a have a decent thread model. PHP was not designed for this anyway because of the share nothing model. Like the slides says "Shared data is pushed down to the data-store layer" like for example MySQL.
Alternatives
I really think you should try the alternatives if you want to do any comet/long polling. You could use many languages like for example:
Java/JVM: Jetty continuations.
Python: Dustin's slosh.
Erlang: Popular language for comet/etc.
Lua, Ruby, C, Perl just to name a few.
Just performing a simple google search, will show you a lot alternatives also PHP(which I think on any big load will kill your server).
mod_php is not the only way to use PHP. You can use fastcgi. PHP must be compiled with --enable-fastcgi.
PHP as FastCGI: http://www.fastcgi.com/drupal/node/5?q=node/10
You may also try https://github.com/reactphp/react
React is a low-level library for event-driven programming in PHP. At its core is an event loop, on top of which it provides low-level utilities, such as: Streams abstraction, async dns resolver, network client/server, http client/server, interaction with processes. Third-party libraries can use these components to create async network clients/servers and more.
The event loop is based on the reactor pattern (hence the name) and strongly inspired by libraries such as EventMachine (Ruby), Twisted (Python) and Node.js (V8).
The introductory example shows a simple HTTP server listening on port 1337:
<?php
$i = 0;
$app = function ($request, $response) use (&$i) {
$i++;
$text = "This is request number $i.\n";
$headers = array('Content-Type' => 'text/plain');
$response->writeHead(200, $headers);
$response->end($text);
};
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);
$http->on('request', $app);
$socket->listen(1337);
$loop->run();
I'm having a similar issue. One option I'm finding interesting is to use an existing Comet server, like cometd-java or cometd-python, as the core message hub. Your PHP code is then just a client to the Comet server -- it can post or read messages from channels, just like other clients.
There's an interesting code snippet linked here: http://morglog.org/?p=22=1 that implements part of this method (although there are bits of debug code spread around, too).
I'm current implementing a scalable PHP Comet server using socket functions. It is called 'phet' ( [ph]p com[et] )
Project page: http://github.com/Tim-Smart/phet
Free free to join in on development. I have currently managed to get most of the server logic done, just need to finish off the client side stuff.
EDIT: Recently added 'Multi-threading' capabilities using the pcntl_fork method :)
You'll have a hard time implementing comet in PHP, just because of it's inherent single-threaded-ness.
Check out Websync On-Demand - the service lets you integrate PHP via server-side publishing, offloading the heavy concurrent connection stuff, and will let you create a real-time chat app in no time.
A new module just came out for the nginx web server that'll allow Comet with any language, including PHP.
http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/
You will have to create your own server in PHP. Using Apache/mod_php or even fastcgi will not scale at all. A few years old, but can get you started:
PHP-Comet-Server:
http://sourceforge.net/projects/comet/
I think this is more an issue that having a lot of apache threads running all the time is a problem. That will existing with any language if it works via apache in the same way as PHP (usually) does.