From b6e333ac68ab7078789b1227af2d9d626b8333e3 Mon Sep 17 00:00:00 2001 From: shaneharter Date: Wed, 9 Feb 2011 07:28:22 -0800 Subject: [PATCH] --- README | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/README b/README index 7b1efe1..ae40fb4 100644 --- a/README +++ b/README @@ -1,6 +1,10 @@ PHP-Daemon -Create solid, long-running PHP daemon processes by extending this Core_Daemon base class. It includes process management with forking and auto-restart features, signal handling, logging and alerts, and a locking mechanism to prevent multiple simultaneous instances. +Create solid, long-running PHP daemon processes by extending this Core_Daemon base class. Unlike other popular daemon libraries, PHP-Daemon has a built-in timer. By setting the loop interval and providing an execute method, the library runs the while loop for you and calls your execute() method at the desired frequency. + +Crontab begins to work poorly when you have tasks that need to run every minute or two, and it has no support for running tasks every second or sub-second. Using PHP-Daemon you can run a task at any interval you require, whether that's every 10 seconds or 10 times per second. + +I use this in production. It includes many features to make it durable and stable for my mission-critical uses. Requires: PHP 5.3 or Higher @@ -10,13 +14,31 @@ Memcache Connection Notable Features: -Loop Frequency -The internal run loop can run at whatever frequency you define. If you wish it to execute 5 times per second, or once every 5 seconds, all you have to do is set the ->loop_interval property. If do set it at '5', and your code takes 2 seconds to execute, it will sleep for the next 3 seconds, wake up, and iterate. If you set it at '5' and it's still running at 5 seconds, it will log it as an error condition. +* Built-In while() loop and micro-time timer. +Example: You set "->loop_interval=1". The PHP-Daemon will call your execute() method and time it. Suppose it takes 0.2 seconds. Upon its completion, the timer will sleep for the remaining 8/10 second. It wakes-up and then iterates. If your execute() method does not return before the end of the loop_interval (1 second in this case), an error will be logged. But since the execute() method is blocking, the next iteration will not begin until the first is complete. + +* Braindead-Simple Forking for tasks that can be parallelized +Suppose your execute() method needed to push its results to an external API. If your interval is at 1 second you just don't have enough time to use an external resource. In these instances, PHP-Daemon provides a fork() method. It accepts a callback (todo: a Closure). When called, it spawns a child process, executes the callback, and exits. You have to be careful, dozens of long-running, possibly hung child processes is not good. But when used carefully it gives you a very simple, very powerful tool and you don't have to worry about mastering the idiosyncrasies of PHP forking. + +* Auto Restart +No matter how diligent you are, memory bloat can occur. PHP-Daemon is able to auto-restart itself both as an attempt to recover from a fatal error, and on a user-defined interval to combat memory bloat. Only available when running in "Daemon mode" (-d at the command prompt), the built-in timer will track total runtime and when it hits the threshold you've set in the ini file, it will perform a graceful restart. -Signal Handling -The daemon listens for 3 signals: SIGINT, SIGHUP, SIGUSR1. When you send the Daemon a standard 'kill [pid]' SIGINT, it will do an ordered shutdown: It will finish the current iteration of the run loop and then shutdown. If you send a 'kill -1 [pid]' HUP command, it will restart the daemon. And if you send a 'kill -10 [pid]' USR1 signal, it will respond by dumping a block of debug variables to either the log or stdout or both, depending on how you configure logging. +* Signal Handling +By default PHP-Daemon listens for 3 signals: SIGINT, SIGHUP, SIGUSR1. When you send the Daemon a standard 'kill [pid]' SIGINT, it will do an graceful shutdown: It will finish the current iteration of the run loop and then shutdown. If you send a 'kill -1 [pid]' HUP command, it will trigger the auto-restart feature. And if you send a 'kill -10 [pid]' SIGUSR1, it will respond by dumping a block of runtime variables to either the log or stdout or both, depending on how you configure logging. + +* Process Heartbeat +Every iteration, a "Heartbeat" is written to a special key in Memcache containing the PID of the process that wrote it. When a daemon starts, it checks that key for an existing heartbeat. If one is heard, it will instantly shut down to prevent multiple running instances of the same daemon. You can also use the heatbeat to monitor the daemon uptime. + +* Memcache Wrapper +A small Memcache wrapper is included that implements easy namespacing but most importantly, auto_retry functionality. In our high-throughput memcache environment we occasionally have an issue where memcache was blocking at that specific microsecond and a key couldn't be written. To avoid this crashing the Daemon, auto-retry functionality was added. This feature will try several times to write the key -- until it reaches the timeout you specify. + +* Simple Logging +By providing a filename, either staticly via the ->log_file property or dynamically by overloading the ->log_file() method, the system will keep a simple log file format, writing the timestamp, PID, and message. The PHP-Daemon system will log noteworthy events and you can easily add your own entries by calling either the ->log($message) method or, if appropriate, the ->fatal_error($message) method. An "alert" flag can be set that will email the $message to the distribution list you define in your constructor. + +* Simple Config Loading +The daemon requires a config file with at least one key: config.auto_restart_interval. You can add any additional settings in there to control your daemon at runtime. All the settings are available by reading ->config[$section][$key]. -Command Line Switches +* Command Line Switches You can run a '-H' help command when you run the Daemon. It will dump a help menu that looks like this, but can be easily overridden for your daemon: Example_Daemon @@ -30,22 +52,6 @@ You can run a '-H' help command when you run the Daemon. It will dump a help men -H Shows this help -p PID_FILE File to write process ID out to -Auto Restart -When run in Daemon mode (-d at the command prompt), the system will keep an internal clock of it's runtime. When it reaches the point set in the config.auto_restart_interval key, it will automatically restart itself by calling itself using an exec() command and then killing the mature process in favor of the newly created. Additionally, when a fatal error is thrown, if it's been running for more than 10 seconds, it'll log the fatal but then attempt to recover by restarting itself. - -Memcache Heartbeat -Every iteration, a "Heartbeat" is written to a special key in Memcache containing the PID of the process that wrote it. When a daemon starts, it checks that key for an existing heartbeat. If one is heard, it will gracefully shut down. You could also write external systems that poll that same key. - -Memcache Wrapper -A small Memcache wrapper is included that implements auto_retry functionality. This adds more redundancy to Memcache to prevent a crash condition in the event where, at that specific microsecond, memcache was blocking and a key couldn't be written. - -Simple Logging -By providing a filename, either staticly via the ->log_file property or dynamically by overloading the ->log_file() method, the system will keep a simple log file format, writing the timestamp, PID, and message. You can easily add entries to the log file throught your custom code by calling either the ->log($message) method or, if appropriate, the ->fatal_error($message) method. - -Simple Config Loading -The daemon requires a config file with at least one key: config.auto_restart_interval. You can add any additional settings in there to control your daemon at runtime. All the settings are available by reading ->config[$section][$key]. - - TODO: 1. Replace this simple logging code (which grew more complex over time) with ZendLog or similar.