Skip to content

start-stop-daemon, Gearman and a little PHP

The scope of this blog entry is to give you a quick and dirty demo for start-stop-daemon together with a short use case on Gearman (all on Ubuntu). In this example, I'm using the start-stop-daemon to handle my Gearman workers through an init.d script.

Gearman

Gearman is a queue! But unlike for example most of the backends to Zend_Queue, Gearman provides a little more than just a message queue to send — well — messages from sender to receiver. With Gearman it's trivial to register functions (tasks) on the server to make in order to start a job and to get stuff done.

For me the biggest advantages of Gearman are that it's easy to scale (add a server, start more workers) and that you can get work done in another language without building an API of some sort in between. Gearman is that API.

Back to start-stop-daemon

start-stop-daemon is a facility to start and stop programs on system start and shutdown. On recent Ubuntus most of the scripts located in /etc/init.d/ make use of it already. It provides a simple high-level API to system calls — such as stopping a process, starting it in a background, running it under a user and the glue, such as writing a pid file.

My gearman start script

Once adjusted, register it with the rc-system: update-rc.d script defaults. This will take care of the script being run during the boot process and before shutdown is completed.

A little more detail

The script may be called with /etc/init.d/script start|stop|restart (the pipes designated "or").

Upon start, we write a pidfile to /var/run and start the process. The same pidfile is used on stop — simple as that. The rest of it is hidden behind start-stop-daemon which takes care of the ugly rest for us.

Caching for dummies

Caching is one of the things recommended whenever something is slow — "Your [database, website, server]? Well, duh! You need a cache!".

All things aside, it's not always easy to cache stuff. I find myself often in situations where I can't cache at all or where a caching solution is complex as hell to implement. All of the sudden you need to dissect your page and lazy load half of it with Ajax — bah. And that's just because those users never want to wait for a cache to expire or invalidate. They just expect the most recent ever! :-)

Sometimes however, caching can be so trivial, it even hurts.

Bypass the application server

There are lots of different techniques and strategies to employ when you start to think about caching. The fastest albeit not always available method is to bypass your app server stack completely. And here's how. :-)

An example

My example is a pet project of mine where I display screenshots of different news outlets which are taken every 3 (three) hours — 0:00, 3:00 AM, 6:00 AM, 9:00 AM, 12:00 PM, 3:00 PM, 6:00 PM, 9:00 PM and so on. In between those fixed dates, the page basically never changes and why would I need PHP to render a page if it didn't change since the last request?

Correct, I don't! :)

And here's what I did to setup my cache:

  • Apache 1.3.x (!) and mod_php5
  • my homepage: docroot/home.php
  • httpd.conf: DirectoryIndex index.html home.php
  • a cronjob: */10 * * * * fetch -q -o docroot/index.html http://example.org/home.php

In greater detail

Homepage

The home.php does all the PHP funkyness whenever I need a fresh rendered version of my website to track an error, or adjust something.

DirectoryIndex

If I ever delete my cache (index.html), my website will still be available. The DirectoryIndex will use home.php next and the request will be a little slower and also more expensive on my side, but the website will continue to work.

Cronjob

The cronjob will issue a HTTP request (GET) using fetch against my homepage and save the result to my index.html. It's really so simple, it hurts. Currently, this cronjob is executed every 10 minutes so I can fiddle with the design and deploy a change more easily, but I could run that cronjob every hour or every few hours as well.

If you don't have fetch, try the following wget command:

wget -q -O docroot/index.html http://example.org/home.php

Fin

That's all, a really simple cache which bypasses your application server. Enjoy!

If you're in for another nifty solution, I suggest you read Brandon Savage's article on caching with the Zend Framework and/or take a look at nginx+Memcached.