Tuesday, September 18, 2007

Why to use a daemon ?

In a standard web context, i.e. with a server executing PHP scripts to response clients' requests, every action asked by the clients is executed during the time the server build the response. For example sending a email to a lot of recipients will cause the execution of the following actions :
  • Get every email addresses the mailing should go to.
  • Foreach email addresses send the mail
These actions, more precisely the one sending the mail, can take some time, and repeating it hundreds of times could cause a timeout to the client's request. What happens then ? The emails not send before the timeout will never be sent, and the system will remain in an knwow state.

Asynchronous calls

To avoid this bad behaviour, a method called asynchronous call can be used. The principle is the following : insead of doing the whole action during the response, the action is put into a queue and is performed by another process which is independant of the client's request, process call "daemon".

The daemon will then look at the queue to check if there is some action to take, and do them until the queue is empty. When the queue is empty, it will wait until some new job come into the queue.

Asychronous calls are then implemented with two parts :
  • A queue which will contain the jobs to do
  • A daemon which will do the jobs in the queue.
This two parts will be largely used later in the concept and in the implementation.

7 comments:

Anonymous said...

sonic server daemon might be worth a look

KillerWhile said...

Thanks for this comment. I didn't know sonic server.

For more information about it, go to http://dev.pedemont.com/sonic/

Anonymous said...

Well, I sincerely hope this project is still alive! It is cool!

Actually, I need them alive, since I´m using it in production! :)

Everythig is working fine. But i got this
"PHP Warning: sem_acquire(): failed to acquire key 0x67018010: Invalid argument in"
when a try to stop de proccess.

I believe this is because the I use "kill" to stop it. A thread is dying after the main thread?

How can I stop the daemon nicely? Or how can I handle start, stop and restart ??

Congratulations for the great work!

Anonymous said...

I forgot to say:

I have 4 alike applications. Each one has their own number of threads. and the problem seens to happen only with 2 or more of then running simultaneously. All the 4 start ok, but when the events are fired, and the threads are created, some conflict occurs! and they died after the "sem_acquire(): failed to acqui" error.

Thanks!

kvz said...

Still alpha, but if you want to create a PHP daemon, conciser using System_Daemon

Install like this:
aptitude -y update
aptitude -y install php-pear
pear install -f system_daemon

Use like this:
// Include PEAR's Daemon Class
require_once "System/Daemon.php";

// Bare minimum setup
System_Daemon::setOption("appName", "mydaemon");

// Spawn Deamon!
System_Daemon::start();

// Your PHP Here!
while (true) {
doTask();
}

// Stop daemon!
System_Daemon::stop();

DaniKrom said...

I just submitted an enhanced version of this daemon to phpclasses.org as "phpmultithreadeddaemon2"

It might still be pending approval:
http://www.phpclasses.org/browse/package/5446.html

DaniKrom said...

@Dino - I'm using my enhanced deamon in production too.
You should be able to use a regular 'kill', and it will terminate gracefully as soon as all children end. The key is that you need to kill the original parent process, NOT any of the child processes.

I have in my to-do list (before year-end) to make it more Unix-compliant (CentOS/RedHat) in terms of where it stores its pid file (id of parent process), proper "registration" scripts under /etc/init.d and /etc/rc?.d, and defaults for logging under something like /var/log/DAEMON_NAME.log.

The hooks for all this are all there -- it traps SIGTERM (default kill signal), and SIGHUP (default "reload" signal.

With all of that said, I will also be taking a look at sonic and maybe the Pear system daemon.