This post is based upon some content within our PHP OO training course (which covers design patterns).
The circuit breaker design pattern is a fairly simple, and handy approach to dealing with remote services which may be offline. To explain the pattern, here’s a semi-true story –
So, imagine the front page of a website includes some output from talking to twitter. However, one day twitter is offline – and all visitors to the site start to experience a 10-15 second delay in page load time. You investigate the problem and discover it’s due to Twitter being offline – in that all requests to it are timing out. What would be nice at this point in time is if your code could have known in advance that Twitter was offline and skipped making a request on it – therefore saving the end users from experiencing a page load delay.
In order to implement the above, we need some sort of shared state between requests – within a PHP context, we could use something like memcache or APC (both are fast and pretty simple to use).
So, before your code checks a remote service, it checks the circuit breaker’s status. If the circuit breaker says “ok” then your code talks to the remote service and notifies the circuit breaker of the outcome (success or failure). If more than a set number of failures occur within a set time period then the circuit breaker changes state and your code can therefore avoid experiencing whatever timeouts may have otherwise occurred.
Pseudo code to illustrate the above could look like :
<?php $cb = new CircuitBreaker('talking_to_twitter'); if($cb->isOk()) { $url = 'http://search.twitter.com/search.json?q=cake'; $json = @file_get_contents($url); if(false === $json) { // immediate problem with twitter - // tell the circuit breaker. $cb->fail(); } else { // let's try and decode the data - check it's valid. $data = @json_decode($json); if(false === $data || !isset($data['completed_in'])) { $cb->fail(); } else { // everything looks good... tell the circuit breaker // and print something trivial out. $cb->success(); echo $data['results'][0]['text']; } } } else { // circuit breaker thinks twitter is ill, so don't bother trying echo "Sorry, twitter is down :-( "; }
Unfortunately there don’t seem to be many PHP CircuitBreakers around – the best examples I can find (outside of what I think is proprietary code belonging to a customer) is this post (which uses a database) and this proposal for one to go into the Zend Framework.
A good circuit breaker would need to :
- Support multiple instances (e.g. one for Twitter, one for talking to Google or whatever)
- Support variable timeouts and thresholds
- Support different storage ‘backends’ (e.g. memcache, APC, MySQL (perhaps) or fileSystem) – at which point it might be best for it to just use Zend Cache.