Are you fed up with all the interdependencies in your applications? Want to be able to scale your business application across multiple servers without hassle? Event-driven architectures to the rescue! In this talk I show how to divide your tasks into small, perfectly scalable parts, empowering you to either scale with your own servers or benefit from cloud computing technologies.
6. Fowler, PoEAA: “Transaction Scripts”
Retrieve Required Data from Database
Process Data
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 4 / 42
7. Fowler, PoEAA: “Transaction Scripts”
Retrieve Required Data from Database
Process Data
Make changes persistent
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 4 / 42
8. Fowler, PoEAA: “Transaction Scripts”
Retrieve Required Data from Database
Process Data
Make changes persistent
Show the user some output
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 4 / 42
9. Fowler, PoEAA: “Transaction Scripts”
Retrieve Required Data from Database
Process Data
Make changes persistent
Show the user some output
Repeat.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 4 / 42
10. A Simple Application: Photo
Community
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 5 / 42
11. Photo
class Photo
{
public $id ;
public $name ;
public $tags = array () ;
public $user = null ;
public $metadata = array () ;
public $originalFile = " " ;
public $thumbnailFile = " " ;
public $created = 0;
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 6 / 42
12. Tags and User
class User
{
public $id ;
public $username ;
public $friends = array () ;
public $photos = array () ;
}
class Tag
{
public $id ;
public $name ;
public $photos = array () ;
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 7 / 42
13. Photo Service
interface PhotoService
{
function u p l o a d RequestIsValid ( $post , $files ) ;
function findOrCreateTags ( array $tagNames ) ;
function createPhoto ( $name , array $tags , User $user ) ;
function saveToDb ( Photo $photo ) ;
function e x t ra c tExifMetadata ( Photo $photo ) ;
function performResizes ( Photo $photo ) ;
function m o v e U p lo aded Photo File ( Photo $photo , $file ) ;
function notifyFriends ( Photo $photo ) ;
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 8 / 42
14. Upload new Photo
$user = getSessionUser () ;
$service = new PhotoServiceImpl () ;
if ( $service - > u p l o a d RequestIsValid ( $_POST , $_FILES ) ) {
// assign $tagNames , $name , $tempFile from Request
$tags = $service - > findOrCreateTags ( $tagNames ) ;
$photo = $service - > createPhoto ( $name , $tags , $user ) ;
$service - > saveToDb ( $photo ) ;
$service - > m o v e U p loade dPho toFil e ( $photo , $tempFile ) ;
$service - > ex t r actExifMetadata ( $photo ) ;
$service - > performResizes ( $photo ) ;
$service - > notifyFriends ( $photo ) ;
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 9 / 42
21. You are always required to change the
core application!
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 11 / 42
22. You are always required to change the
core application!
1. Lots of Coupling.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 11 / 42
23. You are always required to change the
core application!
1. Lots of Coupling.
2. Potential for great complexity.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 11 / 42
24. You are always required to change the
core application!
1. Lots of Coupling.
2. Potential for great complexity.
3. Hard to maintain and test.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 11 / 42
25. You are always required to change the
core application!
1. Lots of Coupling.
2. Potential for great complexity.
3. Hard to maintain and test.
4. Not easily scaleable.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 11 / 42
26. Cronjobs to the Rescue?
Put work in a queue
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 12 / 42
27. Cronjobs to the Rescue?
Put work in a queue
Let a cronjob pick it up
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 12 / 42
28. Cronjobs to the Rescue?
Put work in a queue
Let a cronjob pick it up
Or find work with a query
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 12 / 42
29. Cronjobs to the Rescue?
Put work in a queue
Let a cronjob pick it up
Or find work with a query
But:
Not necessarily scaleable or decoupling.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 12 / 42
30. Cronjobs to the Rescue?
Put work in a queue
Let a cronjob pick it up
Or find work with a query
But:
Not necessarily scaleable or decoupling.
Single-Threaded
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 12 / 42
31. Cronjobs to the Rescue?
Put work in a queue
Let a cronjob pick it up
Or find work with a query
But:
Not necessarily scaleable or decoupling.
Single-Threaded
Delayed by up to a minute
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 12 / 42
32. Event-Driven Architectures
A software architecture where loosly
coupled components communicate with
each other by triggering events.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 13 / 42
37. What is an Event?
“An event is a significant
change in state, which can be
triggered from inside or outside
the application.”
Wikipedia
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 15 / 42
38. What is an Event?
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 16 / 42
42. Subject-Observer Pattern #2
class PhotoUploader implements SplObserver
{
function update ( SplSubject $photo ) {
$this - > moveUploadedFile ( $photo ) ;
}
// ...
}
class Pho to T hu m b Ge n erator implements SplObserver
{
function update ( SplSubject $photo ) {
$this - > performResizes ( $photo ) ;
}
// ...
}
class Ph o t o M e t a d a t a Ext ra ct or implements SplObserver { }
class N ew P h o t o F r i e n d sN o ti f ie r implements SplObserver { }
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 20 / 42
43. Subject-Observer Pattern #3
class Photo implements SplSubject
{
private $observers = null ;
function __construct () {
$this - > observers = new SplObjectStorage () ;
$this - > attach ( new PhotoUploader () ) ;
$this - > attach ( new PhotoThumbGenerator () ) ;
$this - > attach ( new P ho to Met ad at aEx tr ac tor () ) ;
$this - > attach ( new Ne wP h ot o Fr ie n ds No t if i er () ) ;
}
function notify () {
foreach ( $this - > observers AS $observer ) {
$observer - > update ( $this ) ;
}
}
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 21 / 42
44. Subject-Observer Pattern #4
// $service instanceof PhotoService
if ( $service - > u p l o a d RequestIsValid ( $_POST , $_FILES ) ) {
// assign $tagNames , $name , $tempFile from Request
$tags = $service - > findOrCreateTags ( $tagNames ) ;
$photo = $service - > createPhoto ( $name , $tags , $user ) ;
$service - > m o v e U p loade dPho toFil e ( $photo , $tempFile ) ;
$service - > ex t r actExifMetadata ( $photo ) ;
$service - > performResizes ( $photo ) ;
$service - > notifyFriends ( $photo ) ;
$service - > saveToDb ( $photo ) ;
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 22 / 42
52. Event-Dispatcher Pattern #3
$dispatcher = new EventDispatcher () ;
$dispatcher - > attach ( " pre_save_photo " , array (
new P hotoVi rusScanner () ,
new P hotoIs ValidImage () ,
));
$dispatcher - > attach ( " post_save_photo " , array (
new P ho t o Th u m bG enerator () ,
new PhotoCdnUploader () ,
new P h o t o M e t a d a t aE xt rac to r () ,
new N e w P h o t o F r i en d sN ot i fi e r ()
));
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 27 / 42
55. Attention!
Avoid using a shared Database
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 30 / 42
56. Open Questions
And how is this gonna
save me Request Time?
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 31 / 42
57. Open Questions
I know all this,
what has this to do with the Cloud?
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 32 / 42
61. Gearman #2
Installing on Linux is fairly easy already:
root@benny - pc :~ $ wget http : // launchpad . net / gearmand / trunk
/0.10/+ download / gearmand -0.10. tar . gz
root@benny - pc :~ $ tar xzvf gearmand -0.10. tar . gz
root@benny - pc :~ $ cd gearmand -0.10. tar . gz
root@benny - pc :~/ gearmand -0.10 $ ./ configure
root@benny - pc :~/ gearmand -0.10 $ make
root@benny - pc :~/ gearmand -0.10 $ make install
root@benny - pc :~/ gearmand -0.10 $ ldconfig
root@benny - pc :~/ gearmand -0.10 $ pecl install gearman - beta
Use packages daemonstools and
start-stop-daemon to manage workers and server
respectively.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 36 / 42
62. PHP Gearman-Dispatcher
class Ge a r m a n E v e n t D isp at ch er
{
private $client ;
private $list = array () ;
function __construct () {
$this - > client = new GearmanClient () ;
$this - > client - > addServer ( " 127.0.0.1 " ) ;
}
function notify ( $channel , $context ) { }
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 37 / 42
63. PHP Gearman-Dispatcher
class Ge a r m a n E v e n t D isp at ch er
{
function notify ( $channel , $context ) {
$contextData = serialize ( $context ) ;
foreach ( $this - > list [ $channel ] AS $listener ) {
$li stenerTaskName = $listener - > getTaskName () ;
if ( $listener - > isAsync () ) {
$this - > client - > doBackground (
$listenerTaskName , $contextData ) ;
} else {
$this - > client - > do (
$listenerTaskName , $contextData ) ;
}
}
}
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 38 / 42
64. Gearman Worker
$uploader = new LoadUnserializer ( new PhotoUploader () ) ;
$thumbGenerator = new LoadUnserializer (
new P ho t o Th u m bG enerator ()
);
$worker = new GearmanWorker () ;
$worker - > addServer ( " 127.0.0.1 " ) ;
$worker - > addFunction ( " upload_photo " ,
array ( $uploader , ’ update ’)
);
$worker - > addFunction ( " generate_thumb " ,
array ( $thumbGenerator , ’ update ’)
);
while ( $worker - > work () ) {
// handle errors and return values here ..
}
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 39 / 42
65. No need to stop here!
We only looked at the model.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 40 / 42
66. No need to stop here!
We only looked at the model.
Controller/View can also be an
Event-Dispatcher.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 40 / 42
67. No need to stop here!
We only looked at the model.
Controller/View can also be an
Event-Dispatcher.
Call several independant model
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 40 / 42
68. No need to stop here!
We only looked at the model.
Controller/View can also be an
Event-Dispatcher.
Call several independant model
Pre-calculate Ajax calls in main controller.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 40 / 42
69. No need to stop here!
We only looked at the model.
Controller/View can also be an
Event-Dispatcher.
Call several independant model
Pre-calculate Ajax calls in main controller.
Run your Test-Suite on several machines, in
parallel.
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 40 / 42
70. No need to stop here!
We only looked at the model.
Controller/View can also be an
Event-Dispatcher.
Call several independant model
Pre-calculate Ajax calls in main controller.
Run your Test-Suite on several machines, in
parallel.
Any more ideas?
Eberlei (direkt effekt GmbH) Event-Driven Architectures IPC 09, Karlsruhe 40 / 42