SlideShare a Scribd company logo
1 of 154
Work Queues
                      with Gearman and CodeIgniter




CI Conf ’12 - San Francisco


Erik Giberti - JD Supra
Senior Developer
@giberti
erik@jdsupra.com
Who Am I?
What’s a Work Queue Anyway?
What’s a Work Queue Anyway?

  “A sequence of stored data or programs awaiting
  processing.”
    ~ American Heritage Dictionary
What’s a Work Queue Anyway?

  “A sequence of stored data or programs awaiting
  processing.”
    ~ American Heritage Dictionary



  “[F]or storing messages as they travel between
  computers.”
    ~ Amazon SQS site
What’s a Work Queue Anyway?

  “A sequence of stored data or programs awaiting
  processing.”
    ~ American Heritage Dictionary



  “[F]or storing messages as they travel between
  computers.”
    ~ Amazon SQS site



  “[I]t’s the nervous system for how distributed
  processing communicates”
    ~ Gearman site
The Client Worker Pattern
You might be using them already...
You might be using them already...
<?php

    // filename: do_some_work.php
    $conn = mysqli_connect($server, $user, $pass, $database);

    $select = “SELECT * FROM things WHERE status = ‘not done’ ORDER BY timestamp ASC”;
    $res = $conn->query($select);

    while($work = $res->fetch_assoc()){
!
        //
!       // do work
!       //

        $update = “UPDATE things SET status = ‘done’ WHERE id = {$things[‘id’]}”;
!       $conn->query($update);
    }
It works!
It works!
It’s simple to understand
   Get work -> do work -> done.
It works!
It’s simple to understand
   Get work -> do work -> done.
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
It works!
It’s simple to understand
   Get work -> do work -> done.
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
Can be deployed on a different server
   So long as it can talk to the DB
It works!
It’s simple to understand
   Get work -> do work -> done.
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
Can be deployed on a different server
   So long as it can talk to the DB
It’s persistent
   MySQL is pretty good at keeping data
What’s wrong with that?
What’s wrong with that?
Runs at the frequency that cron fires it off
   Can only run once a minute
What’s wrong with that?
Runs at the frequency that cron fires it off
   Can only run once a minute
Single threaded
   Race condition if you start two overlapping threads
   Mitigation strategies
      Have workers kill themselves every minute
      Use modulus to only do certain jobs in certain threads
      Create different DB pools for each worker
What’s wrong with that?
Runs at the frequency that cron fires it off
   Can only run once a minute
Single threaded
   Race condition if you start two overlapping threads
   Mitigation strategies
      Have workers kill themselves every minute
      Use modulus to only do certain jobs in certain threads
      Create different DB pools for each worker

Hits the database at the predefined frequency
   Wasting DB resources
      Hardest tech in most stacks to scale...
Worker Take 2
Worker Take 2

// filename: do_some_work_two.php
$conn = mysqli_connect($server, $user, $pass, $database);

$select = “SELECT * FROM things WHERE status = ‘not done’ ORDER BY timestamp ASC LIMIT 1”;
$done = false;

while(!$done){
     $res = $conn->query($select);
     if($res->num_rows == 1){
!         $work = $res->fetch_assoc();

!        //
!        // do some stuff
!        //

         $update = “UPDATE things SET status = ‘done’ WHERE id = {$things[‘id’]}”;
!        $conn->query($update);

    } else {
!        sleep(1);
    }
}
A little better?
A little better?
It’s simple to understand
   Get work -> do work -> repeat
A little better?
It’s simple to understand
   Get work -> do work -> repeat
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
A little better?
It’s simple to understand
   Get work -> do work -> repeat
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
Can be deployed on a different server
   So long as it can talk to the DB
A little better?
It’s simple to understand
   Get work -> do work -> repeat
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
Can be deployed on a different server
   So long as it can talk to the DB
It’s persistent
   MySQL is pretty good at keeping data
A little better?
It’s simple to understand
   Get work -> do work -> repeat
Can be implemented in other languages
   This job/worker could have been created in Python, Java... whatever!
Can be deployed on a different server
   So long as it can talk to the DB
It’s persistent
   MySQL is pretty good at keeping data
It’s near real time
   Maximum delay of 1 second between jobs
What’s wrong with that?
What’s wrong with that?
Runs at the frequency of the sleep() delay
   1 second waits are pretty good for offloaded tasks
   Can tweak the timing delay to our level of tolerance
      usleep() for finer control of the interval and less than 1 second intervals are
      possible!
What’s wrong with that?
Runs at the frequency of the sleep() delay
   1 second waits are pretty good for offloaded tasks
   Can tweak the timing delay to our level of tolerance
      usleep() for finer control of the interval and less than 1 second intervals are
      possible!

Less likely to hit a race condition
   Same mitigation strategies apply
What’s wrong with that?
Runs at the frequency of the sleep() delay
   1 second waits are pretty good for offloaded tasks
   Can tweak the timing delay to our level of tolerance
      usleep() for finer control of the interval and less than 1 second intervals are
      possible!

Less likely to hit a race condition
   Same mitigation strategies apply
Hits the database even more!
   MySQL can cache queries pretty well with MyISAM tables...
   ... but your using InnoDB ... right?
- a quick history lesson

Originally developed by Danga Interactive to solve specific issues
in the building and hosting of LiveJournal.com. It was originally
announced in 2005 and was written in Perl.
- a quick history lesson

Originally developed by Danga Interactive to solve specific issues
in the building and hosting of LiveJournal.com. It was originally
announced in 2005 and was written in Perl.

It was ported to C by a number of big companies, like Google
and enjoys wide support from the community; not that much
really goes wrong with it.
- a quick history lesson

Originally developed by Danga Interactive to solve specific issues
in the building and hosting of LiveJournal.com. It was originally
announced in 2005 and was written in Perl.

It was ported to C by a number of big companies, like Google
and enjoys wide support from the community; not that much
really goes wrong with it.

Incidentally, Danga Interactive also created Memcached
- a quick history lesson

Originally developed by Danga Interactive to solve specific issues
in the building and hosting of LiveJournal.com. It was originally
announced in 2005 and was written in Perl.

It was ported to C by a number of big companies, like Google
and enjoys wide support from the community; not that much
really goes wrong with it.

Incidentally, Danga Interactive also created Memcached

Danga Interactive exists no more, it was sold to Six Apart then
LiveJournal was sold to SUP. Six Apart was acquired by SAY
Media.
How Gearman Work Queues Stack Up
How Gearman Work Queues Stack Up
They’re simple to understand
  Get work -> do work -> repeat
How Gearman Work Queues Stack Up
They’re simple to understand
  Get work -> do work -> repeat
They can work across languages
  Jobs are simple strings, so they can pass whatever you want
  Additionally, tools exist for things like MySQL to trigger new jobs
How Gearman Work Queues Stack Up
They’re simple to understand
  Get work -> do work -> repeat
They can work across languages
  Jobs are simple strings, so they can pass whatever you want
  Additionally, tools exist for things like MySQL to trigger new jobs
They can work across servers
  Workers don’t need to live where clients do
How Gearman Work Queues Stack Up
They’re simple to understand
   Get work -> do work -> repeat
They can work across languages
   Jobs are simple strings, so they can pass whatever you want
   Additionally, tools exist for things like MySQL to trigger new jobs
They can work across servers
   Workers don’t need to live where clients do
Persistent
   This requires additional configuration
How Gearman Work Queues Stack Up
They’re simple to understand
   Get work -> do work -> repeat
They can work across languages
   Jobs are simple strings, so they can pass whatever you want
   Additionally, tools exist for things like MySQL to trigger new jobs
They can work across servers
   Workers don’t need to live where clients do
Persistent
   This requires additional configuration
Real Time
How Gearman Work Queues Stack Up
They’re simple to understand
   Get work -> do work -> repeat
They can work across languages
   Jobs are simple strings, so they can pass whatever you want
   Additionally, tools exist for things like MySQL to trigger new jobs
They can work across servers
   Workers don’t need to live where clients do
Persistent
   This requires additional configuration
Real Time
Bonus: Can be asynchronous and synchronous!
But I don’t have this sort of workload...
But I don’t have this sort of workload...
                O’RLY?
Have you seen this pattern?
class Upload extends CI_Controller {

!        function index(){

!        !        $this->load->helper(array(‘url’));
!        !        $ul_config = array( /* ... */ );
!        !        $this->load->library(‘upload’, $ul_config);
!        !        if($this->upload->do_upload()){

!        !        !          $file_info = $this->upload->data();
!        !        !          $img_config = array( /* ... */);
!        !        !          $this->load->library(‘image_lib’, $img_config);
!        !        !          $this->image_lib->resize();

!        !        !          // watermark too?
!        !        !          // write to the database
!        !        !          // move to web accessible directory

!        !        !          redirect(site_url(‘controller/next’));

!        !        } else { /* error handling code */ }
!        }
}
It Works
It Works


Reasonably fast in many circumstances
It Works


Reasonably fast in many circumstances



Most modern servers can handle a few of these calls at the
same time.
But there are limitations...
But there are limitations...
Cameras take big images
   The iPhone 4 is a 5 megapixel camera, most files are about 2Mb
   Entry level DSLR cameras are 14 megapixel with 5Mb files
But there are limitations...
Cameras take big images
   The iPhone 4 is a 5 megapixel camera, most files are about 2Mb
   Entry level DSLR cameras are 14 megapixel with 5Mb files
What about multiple uploads
   Present the form, upload one image, process, repeat?
   Provide a block of upload fields and hope it’s enough?
   Use HTML5 / Flash plugin to send multiple files?
      Hope you have enough CPU & RAM to crunch them in parallel.
But there are limitations...
Cameras take big images
   The iPhone 4 is a 5 megapixel camera, most files are about 2Mb
   Entry level DSLR cameras are 14 megapixel with 5Mb files
What about multiple uploads
   Present the form, upload one image, process, repeat?
   Provide a block of upload fields and hope it’s enough?
   Use HTML5 / Flash plugin to send multiple files?
      Hope you have enough CPU & RAM to crunch them in parallel.

Processing may delay the client longer than the default
timeout.
   What happens to your user’s confidence in your product if things are
   slow?
Okay, I’m interested
 how do I add it?
Gearmand runs as another daemon/service in your stack.
  Can be a different server or run along side everything else
Gearmand runs as another daemon/service in your stack.
   Can be a different server or run along side everything else
Gearman’s only job is to facilitate the handling of these
messages
   It can optionally store them in a persistent store to recover from
   system reboots, service restarts, etc.
Gearmand runs as another daemon/service in your stack.
   Can be a different server or run along side everything else
Gearman’s only job is to facilitate the handling of these
messages
   It can optionally store them in a persistent store to recover from
   system reboots, service restarts, etc.
PHP talks to the Gearmand server via an API extension
   Just like MySQL, Memcached, Postgresql, APC and other tools
Gearmand runs as another daemon/service in your stack.
   Can be a different server or run along side everything else
Gearman’s only job is to facilitate the handling of these
messages
   It can optionally store them in a persistent store to recover from
   system reboots, service restarts, etc.
PHP talks to the Gearmand server via an API extension
   Just like MySQL, Memcached, Postgresql, APC and other tools
Your client and worker code pass messages back and forth
to Gearman
   You’ll use a predefined set of PHP function calls to do this
Getting Gearmand running - installers for many systems
Getting Gearmand running - installers for many systems
Linux: apt-get, yum etc
   sudo apt-get install gearmand
   sudo yum install gearmand
Getting Gearmand running - installers for many systems
Linux: apt-get, yum etc
   sudo apt-get install gearmand
   sudo yum install gearmand
Windows: cygwin ...
Getting Gearmand running - installers for many systems
Linux: apt-get, yum etc
   sudo apt-get install gearmand
   sudo yum install gearmand
Windows: cygwin ...
OS X: ...
   Install a package manager: MacPorts, Homebrew
       sudo port install gearmand
       brew install gearmand

   Add a Virtual Machine that has an installer...
Getting Gearmand running - compile your own
Getting Gearmand running - compile your own
Get your dependencies
   sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid-
   devel
Getting Gearmand running - compile your own
Get your dependencies
   sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid-
   devel
Get the latest stable source from gearman.org (Launchpad)
   wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz
Getting Gearmand running - compile your own
Get your dependencies
   sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid-
   devel
Get the latest stable source from gearman.org (Launchpad)
   wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz
Unpack, Compile and Install
   tar -xzf gearmand-0.34.tar.gz
   cd gearmand-0.34.tar.gz
   ./configure
   make
   sudo make install
Getting Gearmand running - compile your own
Get your dependencies
   sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid-
   devel
Get the latest stable source from gearman.org (Launchpad)
   wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz
Unpack, Compile and Install
   tar -xzf gearmand-0.34.tar.gz
   cd gearmand-0.34.tar.gz
   ./configure
   make
   sudo make install
Add appropriate system hooks to start the service on reboot
   chkconfig
   systemctl
   ?
Configuring Gearmand
Configuring Gearmand
Default install is pretty good
   Load gearmand as a background service
   No persistence
   Listens on all available interfaces at port 4730
Configuring Gearmand
Default install is pretty good
   Load gearmand as a background service
   No persistence
   Listens on all available interfaces at port 4730
Persistence
   Easily enabled using
       MySQL based databases (Drizzle, MySQL, MariaDB etc)
       Postgresql
       SQL Lite
       Memcached
   Add the appropriate flags to your init script for details on each
       Docs: http://gearman.org/index.php?id=manual:job_server#persistent_queues
       Example: MySQL
              /sbin/gearmand -q libdrizzle --libdrizzle-host=127.0.0.1 --libdrizzle-user=gearman 
                  --libdrizzle-password=secret --libdrizzle-db=queue --libdrizzle-table=gearman 
                  --libdrizzle-mysql
Configuring Gearmand
Defaults to single thread (mostly)
   Some versions default to use more than one...
   Non-blocking I/O which works very fast with a single thread
   To give each of the internals a dedicated thread use
       /sbin/gearmand -d -t 3
   Additional threads are then used for client worker connections
Configuring Gearmand
Defaults to single thread (mostly)
   Some versions default to use more than one...
   Non-blocking I/O which works very fast with a single thread
   To give each of the internals a dedicated thread use
       /sbin/gearmand -d -t 3
   Additional threads are then used for client worker connections
Security
   Lock gearmand to a single IP
       /sbin/gearmand -d -L 127.0.0.1
   Change the port from the default 4730
       /sbin/gearmand -d -L 127.0.0.1 -p 7003
Configuring Gearmand
Defaults to single thread (mostly)
   Some versions default to use more than one...
   Non-blocking I/O which works very fast with a single thread
   To give each of the internals a dedicated thread use
       /sbin/gearmand -d -t 3
   Additional threads are then used for client worker connections
Security
   Lock gearmand to a single IP
       /sbin/gearmand -d -L 127.0.0.1
   Change the port from the default 4730
       /sbin/gearmand -d -L 127.0.0.1 -p 7003

HTTP Access
   Gearmand supports a pluggable interface architecture and can use HTTP for
   communication. Requests are sent using GET and POST data.
Configuring Gearmand for high availability
Configuring Gearmand for high availability
Gearmand doesn’t replicate data
  May be a weak point depending on your use case
Configuring Gearmand for high availability
Gearmand doesn’t replicate data
  May be a weak point depending on your use case
Redundancy without a load balancer
  In the client logic, add multiple servers and let the driver sort it out
  Workers register themselves with each gearmand server
  Done.
Configuring Gearmand for high availability
Gearmand doesn’t replicate data
  May be a weak point depending on your use case
Redundancy without a load balancer
  In the client logic, add multiple servers and let the driver sort it out
  Workers register themselves with each gearmand server
  Done.
Configuring Gearmand for high availability
Easy to load balance
   Put the two servers behind a load balancer
   Each client connects to the load balancer
   Workers register themselves with each gearmand server
   Done.
Configuring Gearmand for high availability
Easy to load balance
   Put the two servers behind a load balancer
   Each client connects to the load balancer
   Workers register themselves with each gearmand server
   Done.
Adding Gearman API to PHP
Adding Gearman API to PHP
Package managers to the rescue again!
  sudo apt-get install php-pecl-gearman
  sudo yum install php-pecl-gearman
Adding Gearman API to PHP
Package managers to the rescue again!
   sudo apt-get install php-pecl-gearman
   sudo yum install php-pecl-gearman
Pecl
   sudo pecl install gearman
   sudo echo “extension=gearman.so” > /etc/php.d/gearman.ini
Adding Gearman API to PHP
Package managers to the rescue again!
   sudo apt-get install php-pecl-gearman
   sudo yum install php-pecl-gearman
Pecl
   sudo pecl install gearman
   sudo echo “extension=gearman.so” > /etc/php.d/gearman.ini
Quick test
   php -i | grep “gearman support”
       gearman support => enabled
Adding Gearman API to PHP
Package managers to the rescue again!
   sudo apt-get install php-pecl-gearman
   sudo yum install php-pecl-gearman
Pecl
   sudo pecl install gearman
   sudo echo “extension=gearman.so” > /etc/php.d/gearman.ini
Quick test
   php -i | grep “gearman support”
       gearman support => enabled

Restart any services with PHP resident in memory
   Apache, Nginx, etc
Can we get to the code already?
Gearman in PHP - The Client
Clients create the jobs and tasks for the workers to do
Gearman in PHP - The Client
Clients create the jobs and tasks for the workers to do
Create a client object
   $gm = new GearmanClient();
Gearman in PHP - The Client
Clients create the jobs and tasks for the workers to do
Create a client object
   $gm = new GearmanClient();
Define the server(s) to use
   $gm->addServer(); // defaults to localhost:4730
Gearman in PHP - The Client
Clients create the jobs and tasks for the workers to do
Create a client object
   $gm = new GearmanClient();
Define the server(s) to use
   $gm->addServer(); // defaults to localhost:4730
Create the job and wait for a response
   $jobdata = “/* any valid string */”;
   do {
          $res = $gm->do(‘image_resize’, $jobdata);
   } while ($gm->returnCode() != GEARMAN_SUCCESS);
Gearman in PHP - The Client
Clients create the jobs and tasks for the workers to do
Create a client object
   $gm = new GearmanClient();
Define the server(s) to use
   $gm->addServer(); // defaults to localhost:4730
Create the job and wait for a response
   $jobdata = “/* any valid string */”;
   do {
           $res = $gm->do(‘image_resize’, $jobdata);
   } while ($gm->returnCode() != GEARMAN_SUCCESS);
Or don’t
   $jobid = $gm->doBackground(‘image_resize’, $jobdata);
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Define the callbacks
    function callback_resize($job){ /* do stuff */ }
    function callback_watermark($job){ /* do stuff */ }
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Define the callbacks
    function callback_resize($job){ /* do stuff */ }
    function callback_watermark($job){ /* do stuff */ }
Create a worker object
    $gm = new GearmanWorker();
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Define the callbacks
    function callback_resize($job){ /* do stuff */ }
    function callback_watermark($job){ /* do stuff */ }
Create a worker object
    $gm = new GearmanWorker();
Define the server(s) to respond to
    $gm->addServer(); // defaults to localhost:4730
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Define the callbacks
    function callback_resize($job){ /* do stuff */ }
    function callback_watermark($job){ /* do stuff */ }
Create a worker object
    $gm = new GearmanWorker();
Define the server(s) to respond to
    $gm->addServer(); // defaults to localhost:4730
Tell the server which callbacks to use for each task
    $gm->addFunction(‘resize’, ‘callback_resize’);
    $gm->addFunction(‘watermark’, ‘callback_watermark’);
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Define the callbacks
    function callback_resize($job){ /* do stuff */ }
    function callback_watermark($job){ /* do stuff */ }
Create a worker object
    $gm = new GearmanWorker();
Define the server(s) to respond to
    $gm->addServer(); // defaults to localhost:4730
Tell the server which callbacks to use for each task
    $gm->addFunction(‘resize’, ‘callback_resize’);
    $gm->addFunction(‘watermark’, ‘callback_watermark’);
Wait for work to do
    while($gm->work());
Gearman in PHP - The Worker
Workers do the jobs and tasks the clients request
Define the callbacks
    function callback_resize($job){ /* do stuff */ }
    function callback_watermark($job){ /* do stuff */ }
Create a worker object
    $gm = new GearmanWorker();
Define the server(s) to respond to
    $gm->addServer(); // defaults to localhost:4730
Tell the server which callbacks to use for each task
    $gm->addFunction(‘resize’, ‘callback_resize’);
    $gm->addFunction(‘watermark’, ‘callback_watermark’);
Wait for work to do
    while($gm->work());
Callback functions can post status updates on their progress back to the client
    $job->setStatus($numerator/$denominator);
Example Clients in CodeIgniter
class Photos extends CI_Model {

!        public function resize_sync($filename){
!        !        $gm = new GearmanClient();
!        !        $gm->addServer('127.0.0.1', 4730);
!        !        do {
!        !        !         $res = $gm->do('image_resize', $filename);
!        !        !         switch($gm->returnCode()){
!        !        !         !        case GEARMAN_WORK_FAIL:
!        !        !         !        !         return FALSE;
!        !        !         !        case GEARMAN_SUCCESS:
!        !        !         !        !         return TRUE;
!        !        !         }
!        !        } while ($gm->returnCode() != GEARMAN_SUCCESS);!
    !             return TRUE;
!        }

!        public function resize_async($filename){
!        !        $gm = new GearmanClient();
!        !        $gm->addServer('127.0.0.1', 4730);
!        !        $res = $gm->doBackground('image_resize', $filename);
                   if(!$res){ return FALSE; }
    !             return TRUE;
!        }

}
The Callback Handlers
class Photos extends CI_Model {

!        public function resize_sync($filename){ /* ... */ }
!        public function resize_async($filename){ /* ... */ }

!        static public function image_resize($job){
!        !        $filename = $job->workload();
!        !        $CI =& get_instance();
!        !        $config = array(
!        !        !         'source_image' => $filename,
!        !        !         'create_thumbnail' => TRUE,
!        !        !         'maintain_ratio' => TRUE,
!        !        !         'width' => 800,
!        !        !         'height' => 600,
!        !        );
!        !        $CI->image_lib->initialize($config);
!        !        $CI->image_lib->resize();
!        !        $CI->image_lib->clear();
!        !        return true;
!        }
!        static public function image_watermark($job){ /* ... */ }

}
The Worker
class Photos extends CI_Model {

!        public function resize_sync($filename){ /* ... */ }
!        public function resize_async($filename){ /* ... */ }

!        static public function image_resize($job){ /* ... */ }
!        static public function image_watermark($job){ /* ... */ }

!        public function gearman_worker()
!        {!       !
!        !        $gm = new GearmanWorker();
!        !        $gm->addServer('127.0.0.1', 4730);
!        !        $gm->addFunction('image_resize', 'Photos::image_resize');
!        !        $gm->addFunction('image_watermark', 'Photos::image_watermark');
!        !        while($gm->work());
!        }

}
Bringing it all together

class Upload extends CI_Controller {

!        function   index(){
!        !          $this->load->model('photos');
!        !          $this->load->helper(array(‘url’));
!        !          $ul_config = array( /* ... */ );
!        !          $this->load->library(‘upload’, $ul_config);
!        !          if($this->upload->do_upload()){

!        !          !        $file_info = $this->upload->data();
!        !          !        $this->photos->resize_async($file_info['full_path']);

!        !          !        redirect(site_url(‘controller/next’));

!        !          } else { /* error handling code */ }
!        }

!        function worker(){
!        !        $this->load->model('photos');
!        !        $this->photos->gearman_worker();
!        }

}
Running your workers

#!/bin/bash
SCRIPT="index.php upload gearman_worker"!      #   this is your CI controller/method
WORKDIR=/var/www/html/ !    !         !        #   this is your CI app root
MAX_WORKERS=5!     !        !         !        #   number of workers
PHP=/usr/bin/php! !         !         !        #   location of PHP on your system
COUNT=0! !         !        !         !        #   internal use variable

for i in `ps -afe | grep "$SCRIPT" | grep -v grep | awk '{print $2}'`
do
!        COUNT=$((COUNT+1))
done

if test $COUNT -lt $MAX_WORKERS
then
!        cd $WORKDIR
!        $PHP $SCRIPT
else
!        echo There are enough workers running already.
fi
Demo Time: Image Resizing
About the job data
Job data is always a string
About the job data
Job data is always a string
You can serialize data to pass more complex objects
   $data = array(
        ‘filename’ => $filename,
        ‘methods’ => array(‘resize’, ‘watermark’),
        ‘user_id’ => $user_id,
   );
   $jobdata = json_encode($data);
   $gm->doBackground(‘processor’, $jobdata);
About the job data
Job data is always a string
You can serialize data to pass more complex objects
   $data = array(
        ‘filename’ => $filename,
        ‘methods’ => array(‘resize’, ‘watermark’),
        ‘user_id’ => $user_id,
   );
   $jobdata = json_encode($data);
   $gm->doBackground(‘processor’, $jobdata);
And then deserialize it in the worker
   $jobdata = $job->workload();
   $data = json_decode($jobdata, true);
About the job data
In theory, you can pass about 2Gb per message
  Limited by the server protocol which uses a 32 bit integer to define
  message size.
About the job data
In theory, you can pass about 2Gb per message
   Limited by the server protocol which uses a 32 bit integer to define
   message size.
You can pass binary data by encoding it
   $binary_base64 = base64_encode($binary);
About the job data
In theory, you can pass about 2Gb per message
   Limited by the server protocol which uses a 32 bit integer to define
   message size.
You can pass binary data by encoding it
   $binary_base64 = base64_encode($binary);
But use it sparingly
   Any data passed is stored in memory
   and your persistent store (if enabled)
   and is likely on disk already
   Base 64 encoded data is roughly 1 1/2 times the size of the source
   data too
      Compressing the binary data first can help
About the job data
Don’t pass 2Gb objects
About the job data
Don’t pass 2Gb objects
Keep your message data small, less than 64K is perfect
   Amazon’s SQS has a hard limit of 64K
About the job data
Don’t pass 2Gb objects
Keep your message data small, less than 64K is perfect
   Amazon’s SQS has a hard limit of 64K
Pass pointers instead
   Pass paths and filenames instead of files
   Pass cache keys instead of complex class objects
      that won’t deserialize right anyway
About the job data
Don’t pass 2Gb objects
Keep your message data small, less than 64K is perfect
   Amazon’s SQS has a hard limit of 64K
Pass pointers instead
   Pass paths and filenames instead of files
   Pass cache keys instead of complex class objects
      that won’t deserialize right anyway

Gearman is not a data store!
Another Example
Analytics: Problem
We wanted to provide near realtime analytics to our clients
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
   But Google has API limits for getting data out of Analytics
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
   But Google has API limits for getting data out of Analytics
      Only a few thousand requests per day
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
   But Google has API limits for getting data out of Analytics
      Only a few thousand requests per day
      Batching requests was good - but not ideal
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
   But Google has API limits for getting data out of Analytics
      Only a few thousand requests per day
      Batching requests was good - but not ideal
      Data was only monthly, no daily, weekly breakdowns
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
   But Google has API limits for getting data out of Analytics
      Only a few thousand requests per day
      Batching requests was good - but not ideal
      Data was only monthly, no daily, weekly breakdowns
      Still ended up taking weeks to gather a full month of data
Analytics: Problem
We wanted to provide near realtime analytics to our clients
   We liked the data we could scrape out of Google
      Networks Referrers Location
   so we did... for a while... and it was good!
   But Google has API limits for getting data out of Analytics
      Only a few thousand requests per day
      Batching requests was good - but not ideal
      Data was only monthly, no daily, weekly breakdowns
      Still ended up taking weeks to gather a full month of data
   We already had scraped a significant amount of Google data so any
   future collection would need to play nice with the existing data
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
   captures the current url, user agent, referrer and so on
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
   captures the current url, user agent, referrer and so on
   and embeds it as an image tag with a carefully crafted URL for the 1x1
   tracking pixel /statistics/pixel/?ua=Mozilla%2F...
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
   captures the current url, user agent, referrer and so on
   and embeds it as an image tag with a carefully crafted URL for the 1x1
   tracking pixel /statistics/pixel/?ua=Mozilla%2F...
   The pixel request is handled by CodeIgniter, which returns the image,
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
   captures the current url, user agent, referrer and so on
   and embeds it as an image tag with a carefully crafted URL for the 1x1
   tracking pixel /statistics/pixel/?ua=Mozilla%2F...
   The pixel request is handled by CodeIgniter, which returns the image,
   but not before we lookup the country, state, city of the originating IP and
   pass that data into Gearman for future processing.
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
   captures the current url, user agent, referrer and so on
   and embeds it as an image tag with a carefully crafted URL for the 1x1
   tracking pixel /statistics/pixel/?ua=Mozilla%2F...
   The pixel request is handled by CodeIgniter, which returns the image,
   but not before we lookup the country, state, city of the originating IP and
   pass that data into Gearman for future processing.
   The Gearman worker then parses and normalizes the data,
Analytics: Solution
Build our own platform that gathered exactly what we wanted
modeled after Google Analytics
How we did our tracking pixel
   The page has a small javascript file included that
   captures the current url, user agent, referrer and so on
   and embeds it as an image tag with a carefully crafted URL for the 1x1
   tracking pixel /statistics/pixel/?ua=Mozilla%2F...
   The pixel request is handled by CodeIgniter, which returns the image,
   but not before we lookup the country, state, city of the originating IP and
   pass that data into Gearman for future processing.
   The Gearman worker then parses and normalizes the data,
   performs a host lookup on the source IP (which is often very slow) all
   before recording the result in our datastore.
Demo Time: Analytics
Patterns and Recipes
Patterns and Recipes
One to one
  Workers can run in optimized environments for specific tasks
     Example: Using R, Matlab etc to run mathematic analysis and still use CI to for
     the front end
     Example: Run code on a different server to avoid CPU/disk/memory contention
     with Apache etc.
     Example: Run tools on Windows platforms like .NET components for generating
     word files.
Patterns and Recipes
One to one
  Workers can run in optimized environments for specific tasks
     Example: Using R, Matlab etc to run mathematic analysis and still use CI to for
     the front end
     Example: Run code on a different server to avoid CPU/disk/memory contention
     with Apache etc.
     Example: Run tools on Windows platforms like .NET components for generating
     word files.

One to many
  A single client can part out jobs to multiple workers
     Example: Performing TF*IDF analysis on documents to find keywords
     Example: Handling image manipulations in parallel, resizing 2 or 3 new
     thumbnails at a time.
Patterns and Recipes
Many to one
   Multiple clients utilizing a single worker thread
       Share memory across jobs. Arrays are faster than APC, Memcached, MySQL
       Example: Database write buffering (for non critical data only)
       Example: Perform database writes across shards. MySQL UDF inserts a record into
       gearman that’s then re-written out to appropriate user shards
Patterns and Recipes
Many to one
   Multiple clients utilizing a single worker thread
       Share memory across jobs. Arrays are faster than APC, Memcached, MySQL
       Example: Database write buffering (for non critical data only)
       Example: Perform database writes across shards. MySQL UDF inserts a record into
       gearman that’s then re-written out to appropriate user shards

Optimize front end displays
   Example: Pagination optimization
       User requests the first page of data
       Kick off a background task to pre-cache the next page before it’s requested
   Example: Dashboards
       User logs into your site, you fire off background tasks to generate dashboard information
       that user will need
       Workers begin crunching the data and store the results in a cache
       Meanwhile, the user is served a page with spaces allocated for each widget, which are then
       loaded via AJAX
Patterns and Recipes
Delayed/Deferred Processing
  Use whenever tasks would run long or are potentially unreliable
     Preparing images
     Preparing video
     Remote service calls
         Sending content to Twitter, Facebook, LinkedIn...
         Triggering other remote services faxes, emails etc
     Prefetching data
Other Solutions
Other Solutions
Most alternative solutions have APIs for PHP
   Some interface over other protocols like HTTP(s) or memcache,
   which can ease deploying new servers
Other Solutions
Most alternative solutions have APIs for PHP
   Some interface over other protocols like HTTP(s) or memcache,
   which can ease deploying new servers
Alternatives
   Active MQ
   Amazon’s SQS
   Beanstalkd
   Microsoft Message Queuing
   RabbitMQ
   Others - check for activity before adopting
Some helpful tips
Not everything belongs in a work queue
Some helpful tips
Not everything belongs in a work queue
  Queue it if...
Some helpful tips
Not everything belongs in a work queue
  Queue it if...
  the process is intensive on any subsystem, CPU, RAM etc
Some helpful tips
Not everything belongs in a work queue
  Queue it if...
  the process is intensive on any subsystem, CPU, RAM etc
  the process is slow, taking 1/2 second or longer to run, profile your
  app with CodeIgniter’s built-in profiler.
Some helpful tips
Not everything belongs in a work queue
  Queue it if...
  the process is intensive on any subsystem, CPU, RAM etc
  the process is slow, taking 1/2 second or longer to run, profile your
  app with CodeIgniter’s built-in profiler.
  you want the benefit of running in parallel
Some helpful tips
Not everything belongs in a work queue
  Queue it if...
  the process is intensive on any subsystem, CPU, RAM etc
  the process is slow, taking 1/2 second or longer to run, profile your
  app with CodeIgniter’s built-in profiler.
  you want the benefit of running in parallel
Don’t use your database server as your work queue
Some helpful tips
Not everything belongs in a work queue
  Queue it if...
  the process is intensive on any subsystem, CPU, RAM etc
  the process is slow, taking 1/2 second or longer to run, profile your
  app with CodeIgniter’s built-in profiler.
  you want the benefit of running in parallel
Don’t use your database server as your work queue
  It might work short term, but it’s not scaleable.
Some helpful tips
Not everything belongs in a work queue
   Queue it if...
   the process is intensive on any subsystem, CPU, RAM etc
   the process is slow, taking 1/2 second or longer to run, profile your
   app with CodeIgniter’s built-in profiler.
   you want the benefit of running in parallel
Don’t use your database server as your work queue
   It might work short term, but it’s not scaleable.
Persistence comes with a cost
Some helpful tips
Not everything belongs in a work queue
   Queue it if...
   the process is intensive on any subsystem, CPU, RAM etc
   the process is slow, taking 1/2 second or longer to run, profile your
   app with CodeIgniter’s built-in profiler.
   you want the benefit of running in parallel
Don’t use your database server as your work queue
   It might work short term, but it’s not scaleable.
Persistence comes with a cost
   Writes to the datastore are never free and will slow down the queue
Some helpful tips
Not everything belongs in a work queue
   Queue it if...
   the process is intensive on any subsystem, CPU, RAM etc
   the process is slow, taking 1/2 second or longer to run, profile your
   app with CodeIgniter’s built-in profiler.
   you want the benefit of running in parallel
Don’t use your database server as your work queue
   It might work short term, but it’s not scaleable.
Persistence comes with a cost
   Writes to the datastore are never free and will slow down the queue
   Adds an additional layer of stuff to maintain
Questions?
Thank You!
(this slide intentionally left blank)

More Related Content

What's hot

Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::SynchronyFast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::SynchronyKyle Drake
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love itDrupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love itRyan Weaver
 
Building MapAttack
Building MapAttackBuilding MapAttack
Building MapAttackKyle Drake
 
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010singingfish
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9Ilya Grigorik
 
Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkPatrick LaRoche
 
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comRuby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comIlya Grigorik
 
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with BehatGrand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with BehatRyan Weaver
 
Stop Worrying & Love the SQL - A Case Study
Stop Worrying & Love the SQL - A Case StudyStop Worrying & Love the SQL - A Case Study
Stop Worrying & Love the SQL - A Case StudyAll Things Open
 

What's hot (11)

Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::SynchronyFast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love itDrupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
 
Building MapAttack
Building MapAttackBuilding MapAttack
Building MapAttack
 
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
 
Toplog candy elves - HOCM Talk
Toplog candy elves - HOCM TalkToplog candy elves - HOCM Talk
Toplog candy elves - HOCM Talk
 
Scalable talk notes
Scalable talk notesScalable talk notes
Scalable talk notes
 
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comRuby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
 
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with BehatGrand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
 
Stop Worrying & Love the SQL - A Case Study
Stop Worrying & Love the SQL - A Case StudyStop Worrying & Love the SQL - A Case Study
Stop Worrying & Love the SQL - A Case Study
 

Viewers also liked

Analiza Algoritmilor de Sortare pe Arhitecturi Paralele
Analiza Algoritmilor de Sortare pe Arhitecturi ParaleleAnaliza Algoritmilor de Sortare pe Arhitecturi Paralele
Analiza Algoritmilor de Sortare pe Arhitecturi ParaleleRadu Potop
 
01/18/13 US Supreme Court Response (polish)
01/18/13 US Supreme Court Response (polish)01/18/13 US Supreme Court Response (polish)
01/18/13 US Supreme Court Response (polish)VogelDenise
 
IE Big Data Club WEBINAR: Agile iSS Introduction
IE Big Data Club WEBINAR: Agile iSS IntroductionIE Big Data Club WEBINAR: Agile iSS Introduction
IE Big Data Club WEBINAR: Agile iSS IntroductionRoosi Mägi
 
What is the Cloud A Pictorial 2012-Oct-25
What is the Cloud  A Pictorial 2012-Oct-25What is the Cloud  A Pictorial 2012-Oct-25
What is the Cloud A Pictorial 2012-Oct-25Community IT Innovators
 
012813 us supreme court response (finnish)
012813   us supreme court response (finnish)012813   us supreme court response (finnish)
012813 us supreme court response (finnish)VogelDenise
 
Tratamento cirúrgico de fissuras palatinas completas
Tratamento cirúrgico de fissuras palatinas completasTratamento cirúrgico de fissuras palatinas completas
Tratamento cirúrgico de fissuras palatinas completasLucia Regina Cavalcanti
 
020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)
020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)
020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)VogelDenise
 
11/19/12 - Petition For Original Writ et al (PKH) - Supreme Court (Stamped)
11/19/12 - Petition  For Original Writ et al (PKH) - Supreme Court (Stamped)11/19/12 - Petition  For Original Writ et al (PKH) - Supreme Court (Stamped)
11/19/12 - Petition For Original Writ et al (PKH) - Supreme Court (Stamped)VogelDenise
 
122912 public notification (obama & pay pal attacks) - dutch
122912   public notification (obama & pay pal attacks) - dutch122912   public notification (obama & pay pal attacks) - dutch
122912 public notification (obama & pay pal attacks) - dutchVogelDenise
 
Nuremberg crimes against humanity-peace (slovak)
Nuremberg   crimes against humanity-peace (slovak)Nuremberg   crimes against humanity-peace (slovak)
Nuremberg crimes against humanity-peace (slovak)VogelDenise
 
Nuremberg principle turkish
Nuremberg principle   turkishNuremberg principle   turkish
Nuremberg principle turkishVogelDenise
 
JACOB "JACK" LEW - Wikipedia Information
JACOB "JACK" LEW - Wikipedia InformationJACOB "JACK" LEW - Wikipedia Information
JACOB "JACK" LEW - Wikipedia InformationVogelDenise
 
DMA email a multichannel approach to growing your list
DMA email a multichannel approach to growing your listDMA email a multichannel approach to growing your list
DMA email a multichannel approach to growing your listDMA Email Marketing Council
 
01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...
01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...
01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...VogelDenise
 
122912 public notification (obama & pay pal attacks) - georgian
122912   public notification (obama & pay pal attacks) - georgian122912   public notification (obama & pay pal attacks) - georgian
122912 public notification (obama & pay pal attacks) - georgianVogelDenise
 
122312 obama fax (lao)
122312   obama fax (lao)122312   obama fax (lao)
122312 obama fax (lao)VogelDenise
 
Python side projects etssi-jan-2013
Python side projects etssi-jan-2013Python side projects etssi-jan-2013
Python side projects etssi-jan-2013ahmontero
 
050113 fax to judy clarke (boston marathon bombing) - icelandic
050113   fax to judy clarke (boston marathon bombing) - icelandic050113   fax to judy clarke (boston marathon bombing) - icelandic
050113 fax to judy clarke (boston marathon bombing) - icelandicVogelDenise
 
122912 public notification (obama & pay pal attacks) -yiddish
122912   public notification (obama & pay pal attacks) -yiddish122912   public notification (obama & pay pal attacks) -yiddish
122912 public notification (obama & pay pal attacks) -yiddishVogelDenise
 

Viewers also liked (20)

Analiza Algoritmilor de Sortare pe Arhitecturi Paralele
Analiza Algoritmilor de Sortare pe Arhitecturi ParaleleAnaliza Algoritmilor de Sortare pe Arhitecturi Paralele
Analiza Algoritmilor de Sortare pe Arhitecturi Paralele
 
01/18/13 US Supreme Court Response (polish)
01/18/13 US Supreme Court Response (polish)01/18/13 US Supreme Court Response (polish)
01/18/13 US Supreme Court Response (polish)
 
IE Big Data Club WEBINAR: Agile iSS Introduction
IE Big Data Club WEBINAR: Agile iSS IntroductionIE Big Data Club WEBINAR: Agile iSS Introduction
IE Big Data Club WEBINAR: Agile iSS Introduction
 
What is the Cloud A Pictorial 2012-Oct-25
What is the Cloud  A Pictorial 2012-Oct-25What is the Cloud  A Pictorial 2012-Oct-25
What is the Cloud A Pictorial 2012-Oct-25
 
012813 us supreme court response (finnish)
012813   us supreme court response (finnish)012813   us supreme court response (finnish)
012813 us supreme court response (finnish)
 
Granátové jablko
Granátové jablkoGranátové jablko
Granátové jablko
 
Tratamento cirúrgico de fissuras palatinas completas
Tratamento cirúrgico de fissuras palatinas completasTratamento cirúrgico de fissuras palatinas completas
Tratamento cirúrgico de fissuras palatinas completas
 
020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)
020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)
020915 PUBLIC RELEASE EEOC CHARGE AGAINST 1ST HERITAGE CREDIT (Persian)
 
11/19/12 - Petition For Original Writ et al (PKH) - Supreme Court (Stamped)
11/19/12 - Petition  For Original Writ et al (PKH) - Supreme Court (Stamped)11/19/12 - Petition  For Original Writ et al (PKH) - Supreme Court (Stamped)
11/19/12 - Petition For Original Writ et al (PKH) - Supreme Court (Stamped)
 
122912 public notification (obama & pay pal attacks) - dutch
122912   public notification (obama & pay pal attacks) - dutch122912   public notification (obama & pay pal attacks) - dutch
122912 public notification (obama & pay pal attacks) - dutch
 
Nuremberg crimes against humanity-peace (slovak)
Nuremberg   crimes against humanity-peace (slovak)Nuremberg   crimes against humanity-peace (slovak)
Nuremberg crimes against humanity-peace (slovak)
 
Nuremberg principle turkish
Nuremberg principle   turkishNuremberg principle   turkish
Nuremberg principle turkish
 
JACOB "JACK" LEW - Wikipedia Information
JACOB "JACK" LEW - Wikipedia InformationJACOB "JACK" LEW - Wikipedia Information
JACOB "JACK" LEW - Wikipedia Information
 
DMA email a multichannel approach to growing your list
DMA email a multichannel approach to growing your listDMA email a multichannel approach to growing your list
DMA email a multichannel approach to growing your list
 
01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...
01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...
01/06/13 OBAMA FAX CONFIRMATION - Adecco - Notification of COMPROMISEto e Pay...
 
122912 public notification (obama & pay pal attacks) - georgian
122912   public notification (obama & pay pal attacks) - georgian122912   public notification (obama & pay pal attacks) - georgian
122912 public notification (obama & pay pal attacks) - georgian
 
122312 obama fax (lao)
122312   obama fax (lao)122312   obama fax (lao)
122312 obama fax (lao)
 
Python side projects etssi-jan-2013
Python side projects etssi-jan-2013Python side projects etssi-jan-2013
Python side projects etssi-jan-2013
 
050113 fax to judy clarke (boston marathon bombing) - icelandic
050113   fax to judy clarke (boston marathon bombing) - icelandic050113   fax to judy clarke (boston marathon bombing) - icelandic
050113 fax to judy clarke (boston marathon bombing) - icelandic
 
122912 public notification (obama & pay pal attacks) -yiddish
122912   public notification (obama & pay pal attacks) -yiddish122912   public notification (obama & pay pal attacks) -yiddish
122912 public notification (obama & pay pal attacks) -yiddish
 

Similar to Work Queues

Puppet for Sys Admins
Puppet for Sys AdminsPuppet for Sys Admins
Puppet for Sys AdminsPuppet
 
FireWorks workflow software
FireWorks workflow softwareFireWorks workflow software
FireWorks workflow softwareAnubhav Jain
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteDr Nic Williams
 
Continuous Delivery: The Dirty Details
Continuous Delivery: The Dirty DetailsContinuous Delivery: The Dirty Details
Continuous Delivery: The Dirty DetailsMike Brittain
 
AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...
AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...
AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...GeeksLab Odessa
 
DATABASE AUTOMATION with Thousands of database, monitoring and backup
DATABASE AUTOMATION with Thousands of database, monitoring and backupDATABASE AUTOMATION with Thousands of database, monitoring and backup
DATABASE AUTOMATION with Thousands of database, monitoring and backupSaewoong Lee
 
Capistrano, Puppet, and Chef
Capistrano, Puppet, and ChefCapistrano, Puppet, and Chef
Capistrano, Puppet, and ChefDavid Benjamin
 
Free The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainFree The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainKen Collins
 
Pilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil CholewińskiPilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil CholewińskiPilot
 
Airflow - Insane power in a Tiny Box
Airflow - Insane power in a Tiny BoxAirflow - Insane power in a Tiny Box
Airflow - Insane power in a Tiny BoxDovy Paukstys
 
Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!mold
 
Puppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionPuppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionJoshua Thijssen
 
Neo4j Stored Procedure Training Part 1
Neo4j Stored Procedure Training Part 1Neo4j Stored Procedure Training Part 1
Neo4j Stored Procedure Training Part 1Max De Marzi
 
IaC and Immutable Infrastructure with Terraform, Сергей Марченко
IaC and Immutable Infrastructure with Terraform, Сергей МарченкоIaC and Immutable Infrastructure with Terraform, Сергей Марченко
IaC and Immutable Infrastructure with Terraform, Сергей МарченкоSigma Software
 
Systems Monitoring with Prometheus (Devops Ireland April 2015)
Systems Monitoring with Prometheus (Devops Ireland April 2015)Systems Monitoring with Prometheus (Devops Ireland April 2015)
Systems Monitoring with Prometheus (Devops Ireland April 2015)Brian Brazil
 
A Tale of Two Workflows - ChefConf 2014
A Tale of Two Workflows - ChefConf 2014A Tale of Two Workflows - ChefConf 2014
A Tale of Two Workflows - ChefConf 2014Pete Cheslock
 
From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...
From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...
From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...Alexander Dean
 
Inside Bokete: Web Application with Mojolicious and others
Inside Bokete:  Web Application with Mojolicious and othersInside Bokete:  Web Application with Mojolicious and others
Inside Bokete: Web Application with Mojolicious and othersYusuke Wada
 
Consistent Development Environment with Vagrant and Chef
Consistent Development Environment with Vagrant and ChefConsistent Development Environment with Vagrant and Chef
Consistent Development Environment with Vagrant and ChefGerald Villorente
 
DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.Vlad Fedosov
 

Similar to Work Queues (20)

Puppet for Sys Admins
Puppet for Sys AdminsPuppet for Sys Admins
Puppet for Sys Admins
 
FireWorks workflow software
FireWorks workflow softwareFireWorks workflow software
FireWorks workflow software
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
 
Continuous Delivery: The Dirty Details
Continuous Delivery: The Dirty DetailsContinuous Delivery: The Dirty Details
Continuous Delivery: The Dirty Details
 
AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...
AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...
AI&BigData Lab. Александр Конопко "Celos: оркестрирование и тестирование зада...
 
DATABASE AUTOMATION with Thousands of database, monitoring and backup
DATABASE AUTOMATION with Thousands of database, monitoring and backupDATABASE AUTOMATION with Thousands of database, monitoring and backup
DATABASE AUTOMATION with Thousands of database, monitoring and backup
 
Capistrano, Puppet, and Chef
Capistrano, Puppet, and ChefCapistrano, Puppet, and Chef
Capistrano, Puppet, and Chef
 
Free The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainFree The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own Domain
 
Pilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil CholewińskiPilot Tech Talk #10 — Practical automation by Kamil Cholewiński
Pilot Tech Talk #10 — Practical automation by Kamil Cholewiński
 
Airflow - Insane power in a Tiny Box
Airflow - Insane power in a Tiny BoxAirflow - Insane power in a Tiny Box
Airflow - Insane power in a Tiny Box
 
Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!
 
Puppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionPuppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 Edition
 
Neo4j Stored Procedure Training Part 1
Neo4j Stored Procedure Training Part 1Neo4j Stored Procedure Training Part 1
Neo4j Stored Procedure Training Part 1
 
IaC and Immutable Infrastructure with Terraform, Сергей Марченко
IaC and Immutable Infrastructure with Terraform, Сергей МарченкоIaC and Immutable Infrastructure with Terraform, Сергей Марченко
IaC and Immutable Infrastructure with Terraform, Сергей Марченко
 
Systems Monitoring with Prometheus (Devops Ireland April 2015)
Systems Monitoring with Prometheus (Devops Ireland April 2015)Systems Monitoring with Prometheus (Devops Ireland April 2015)
Systems Monitoring with Prometheus (Devops Ireland April 2015)
 
A Tale of Two Workflows - ChefConf 2014
A Tale of Two Workflows - ChefConf 2014A Tale of Two Workflows - ChefConf 2014
A Tale of Two Workflows - ChefConf 2014
 
From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...
From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...
From Zero to Hadoop: a tutorial for getting started writing Hadoop jobs on Am...
 
Inside Bokete: Web Application with Mojolicious and others
Inside Bokete:  Web Application with Mojolicious and othersInside Bokete:  Web Application with Mojolicious and others
Inside Bokete: Web Application with Mojolicious and others
 
Consistent Development Environment with Vagrant and Chef
Consistent Development Environment with Vagrant and ChefConsistent Development Environment with Vagrant and Chef
Consistent Development Environment with Vagrant and Chef
 
DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.DevOps Fest 2020. immutable infrastructure as code. True story.
DevOps Fest 2020. immutable infrastructure as code. True story.
 

More from ciconf

CICONF 2012 - Don't Make Me Read Your Mind
CICONF 2012 - Don't Make Me Read Your MindCICONF 2012 - Don't Make Me Read Your Mind
CICONF 2012 - Don't Make Me Read Your Mindciconf
 
Chef + AWS + CodeIgniter
Chef + AWS + CodeIgniterChef + AWS + CodeIgniter
Chef + AWS + CodeIgniterciconf
 
Pretty Good Practices/Productivity
Pretty Good Practices/ProductivityPretty Good Practices/Productivity
Pretty Good Practices/Productivityciconf
 
Who Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniterWho Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniterciconf
 
Hosting as a Framework
Hosting as a FrameworkHosting as a Framework
Hosting as a Frameworkciconf
 
Zero to Hero in Start-ups
Zero to Hero in Start-upsZero to Hero in Start-ups
Zero to Hero in Start-upsciconf
 
How to use ORM
How to use ORMHow to use ORM
How to use ORMciconf
 

More from ciconf (7)

CICONF 2012 - Don't Make Me Read Your Mind
CICONF 2012 - Don't Make Me Read Your MindCICONF 2012 - Don't Make Me Read Your Mind
CICONF 2012 - Don't Make Me Read Your Mind
 
Chef + AWS + CodeIgniter
Chef + AWS + CodeIgniterChef + AWS + CodeIgniter
Chef + AWS + CodeIgniter
 
Pretty Good Practices/Productivity
Pretty Good Practices/ProductivityPretty Good Practices/Productivity
Pretty Good Practices/Productivity
 
Who Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniterWho Needs Ruby When You've Got CodeIgniter
Who Needs Ruby When You've Got CodeIgniter
 
Hosting as a Framework
Hosting as a FrameworkHosting as a Framework
Hosting as a Framework
 
Zero to Hero in Start-ups
Zero to Hero in Start-upsZero to Hero in Start-ups
Zero to Hero in Start-ups
 
How to use ORM
How to use ORMHow to use ORM
How to use ORM
 

Recently uploaded

DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 

Recently uploaded (20)

DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 

Work Queues

  • 1. Work Queues with Gearman and CodeIgniter CI Conf ’12 - San Francisco Erik Giberti - JD Supra Senior Developer @giberti erik@jdsupra.com
  • 3. What’s a Work Queue Anyway?
  • 4. What’s a Work Queue Anyway? “A sequence of stored data or programs awaiting processing.” ~ American Heritage Dictionary
  • 5. What’s a Work Queue Anyway? “A sequence of stored data or programs awaiting processing.” ~ American Heritage Dictionary “[F]or storing messages as they travel between computers.” ~ Amazon SQS site
  • 6. What’s a Work Queue Anyway? “A sequence of stored data or programs awaiting processing.” ~ American Heritage Dictionary “[F]or storing messages as they travel between computers.” ~ Amazon SQS site “[I]t’s the nervous system for how distributed processing communicates” ~ Gearman site
  • 8. You might be using them already...
  • 9. You might be using them already... <?php // filename: do_some_work.php $conn = mysqli_connect($server, $user, $pass, $database); $select = “SELECT * FROM things WHERE status = ‘not done’ ORDER BY timestamp ASC”; $res = $conn->query($select); while($work = $res->fetch_assoc()){ ! // ! // do work ! // $update = “UPDATE things SET status = ‘done’ WHERE id = {$things[‘id’]}”; ! $conn->query($update); }
  • 11. It works! It’s simple to understand Get work -> do work -> done.
  • 12. It works! It’s simple to understand Get work -> do work -> done. Can be implemented in other languages This job/worker could have been created in Python, Java... whatever!
  • 13. It works! It’s simple to understand Get work -> do work -> done. Can be implemented in other languages This job/worker could have been created in Python, Java... whatever! Can be deployed on a different server So long as it can talk to the DB
  • 14. It works! It’s simple to understand Get work -> do work -> done. Can be implemented in other languages This job/worker could have been created in Python, Java... whatever! Can be deployed on a different server So long as it can talk to the DB It’s persistent MySQL is pretty good at keeping data
  • 16. What’s wrong with that? Runs at the frequency that cron fires it off Can only run once a minute
  • 17. What’s wrong with that? Runs at the frequency that cron fires it off Can only run once a minute Single threaded Race condition if you start two overlapping threads Mitigation strategies Have workers kill themselves every minute Use modulus to only do certain jobs in certain threads Create different DB pools for each worker
  • 18. What’s wrong with that? Runs at the frequency that cron fires it off Can only run once a minute Single threaded Race condition if you start two overlapping threads Mitigation strategies Have workers kill themselves every minute Use modulus to only do certain jobs in certain threads Create different DB pools for each worker Hits the database at the predefined frequency Wasting DB resources Hardest tech in most stacks to scale...
  • 20. Worker Take 2 // filename: do_some_work_two.php $conn = mysqli_connect($server, $user, $pass, $database); $select = “SELECT * FROM things WHERE status = ‘not done’ ORDER BY timestamp ASC LIMIT 1”; $done = false; while(!$done){ $res = $conn->query($select); if($res->num_rows == 1){ ! $work = $res->fetch_assoc(); ! // ! // do some stuff ! // $update = “UPDATE things SET status = ‘done’ WHERE id = {$things[‘id’]}”; ! $conn->query($update); } else { ! sleep(1); } }
  • 22. A little better? It’s simple to understand Get work -> do work -> repeat
  • 23. A little better? It’s simple to understand Get work -> do work -> repeat Can be implemented in other languages This job/worker could have been created in Python, Java... whatever!
  • 24. A little better? It’s simple to understand Get work -> do work -> repeat Can be implemented in other languages This job/worker could have been created in Python, Java... whatever! Can be deployed on a different server So long as it can talk to the DB
  • 25. A little better? It’s simple to understand Get work -> do work -> repeat Can be implemented in other languages This job/worker could have been created in Python, Java... whatever! Can be deployed on a different server So long as it can talk to the DB It’s persistent MySQL is pretty good at keeping data
  • 26. A little better? It’s simple to understand Get work -> do work -> repeat Can be implemented in other languages This job/worker could have been created in Python, Java... whatever! Can be deployed on a different server So long as it can talk to the DB It’s persistent MySQL is pretty good at keeping data It’s near real time Maximum delay of 1 second between jobs
  • 28. What’s wrong with that? Runs at the frequency of the sleep() delay 1 second waits are pretty good for offloaded tasks Can tweak the timing delay to our level of tolerance usleep() for finer control of the interval and less than 1 second intervals are possible!
  • 29. What’s wrong with that? Runs at the frequency of the sleep() delay 1 second waits are pretty good for offloaded tasks Can tweak the timing delay to our level of tolerance usleep() for finer control of the interval and less than 1 second intervals are possible! Less likely to hit a race condition Same mitigation strategies apply
  • 30. What’s wrong with that? Runs at the frequency of the sleep() delay 1 second waits are pretty good for offloaded tasks Can tweak the timing delay to our level of tolerance usleep() for finer control of the interval and less than 1 second intervals are possible! Less likely to hit a race condition Same mitigation strategies apply Hits the database even more! MySQL can cache queries pretty well with MyISAM tables... ... but your using InnoDB ... right?
  • 31. - a quick history lesson Originally developed by Danga Interactive to solve specific issues in the building and hosting of LiveJournal.com. It was originally announced in 2005 and was written in Perl.
  • 32. - a quick history lesson Originally developed by Danga Interactive to solve specific issues in the building and hosting of LiveJournal.com. It was originally announced in 2005 and was written in Perl. It was ported to C by a number of big companies, like Google and enjoys wide support from the community; not that much really goes wrong with it.
  • 33. - a quick history lesson Originally developed by Danga Interactive to solve specific issues in the building and hosting of LiveJournal.com. It was originally announced in 2005 and was written in Perl. It was ported to C by a number of big companies, like Google and enjoys wide support from the community; not that much really goes wrong with it. Incidentally, Danga Interactive also created Memcached
  • 34. - a quick history lesson Originally developed by Danga Interactive to solve specific issues in the building and hosting of LiveJournal.com. It was originally announced in 2005 and was written in Perl. It was ported to C by a number of big companies, like Google and enjoys wide support from the community; not that much really goes wrong with it. Incidentally, Danga Interactive also created Memcached Danga Interactive exists no more, it was sold to Six Apart then LiveJournal was sold to SUP. Six Apart was acquired by SAY Media.
  • 35. How Gearman Work Queues Stack Up
  • 36. How Gearman Work Queues Stack Up They’re simple to understand Get work -> do work -> repeat
  • 37. How Gearman Work Queues Stack Up They’re simple to understand Get work -> do work -> repeat They can work across languages Jobs are simple strings, so they can pass whatever you want Additionally, tools exist for things like MySQL to trigger new jobs
  • 38. How Gearman Work Queues Stack Up They’re simple to understand Get work -> do work -> repeat They can work across languages Jobs are simple strings, so they can pass whatever you want Additionally, tools exist for things like MySQL to trigger new jobs They can work across servers Workers don’t need to live where clients do
  • 39. How Gearman Work Queues Stack Up They’re simple to understand Get work -> do work -> repeat They can work across languages Jobs are simple strings, so they can pass whatever you want Additionally, tools exist for things like MySQL to trigger new jobs They can work across servers Workers don’t need to live where clients do Persistent This requires additional configuration
  • 40. How Gearman Work Queues Stack Up They’re simple to understand Get work -> do work -> repeat They can work across languages Jobs are simple strings, so they can pass whatever you want Additionally, tools exist for things like MySQL to trigger new jobs They can work across servers Workers don’t need to live where clients do Persistent This requires additional configuration Real Time
  • 41. How Gearman Work Queues Stack Up They’re simple to understand Get work -> do work -> repeat They can work across languages Jobs are simple strings, so they can pass whatever you want Additionally, tools exist for things like MySQL to trigger new jobs They can work across servers Workers don’t need to live where clients do Persistent This requires additional configuration Real Time Bonus: Can be asynchronous and synchronous!
  • 42. But I don’t have this sort of workload...
  • 43. But I don’t have this sort of workload... O’RLY?
  • 44. Have you seen this pattern? class Upload extends CI_Controller { ! function index(){ ! ! $this->load->helper(array(‘url’)); ! ! $ul_config = array( /* ... */ ); ! ! $this->load->library(‘upload’, $ul_config); ! ! if($this->upload->do_upload()){ ! ! ! $file_info = $this->upload->data(); ! ! ! $img_config = array( /* ... */); ! ! ! $this->load->library(‘image_lib’, $img_config); ! ! ! $this->image_lib->resize(); ! ! ! // watermark too? ! ! ! // write to the database ! ! ! // move to web accessible directory ! ! ! redirect(site_url(‘controller/next’)); ! ! } else { /* error handling code */ } ! } }
  • 46. It Works Reasonably fast in many circumstances
  • 47. It Works Reasonably fast in many circumstances Most modern servers can handle a few of these calls at the same time.
  • 48. But there are limitations...
  • 49. But there are limitations... Cameras take big images The iPhone 4 is a 5 megapixel camera, most files are about 2Mb Entry level DSLR cameras are 14 megapixel with 5Mb files
  • 50. But there are limitations... Cameras take big images The iPhone 4 is a 5 megapixel camera, most files are about 2Mb Entry level DSLR cameras are 14 megapixel with 5Mb files What about multiple uploads Present the form, upload one image, process, repeat? Provide a block of upload fields and hope it’s enough? Use HTML5 / Flash plugin to send multiple files? Hope you have enough CPU & RAM to crunch them in parallel.
  • 51. But there are limitations... Cameras take big images The iPhone 4 is a 5 megapixel camera, most files are about 2Mb Entry level DSLR cameras are 14 megapixel with 5Mb files What about multiple uploads Present the form, upload one image, process, repeat? Provide a block of upload fields and hope it’s enough? Use HTML5 / Flash plugin to send multiple files? Hope you have enough CPU & RAM to crunch them in parallel. Processing may delay the client longer than the default timeout. What happens to your user’s confidence in your product if things are slow?
  • 52. Okay, I’m interested how do I add it?
  • 53. Gearmand runs as another daemon/service in your stack. Can be a different server or run along side everything else
  • 54. Gearmand runs as another daemon/service in your stack. Can be a different server or run along side everything else Gearman’s only job is to facilitate the handling of these messages It can optionally store them in a persistent store to recover from system reboots, service restarts, etc.
  • 55. Gearmand runs as another daemon/service in your stack. Can be a different server or run along side everything else Gearman’s only job is to facilitate the handling of these messages It can optionally store them in a persistent store to recover from system reboots, service restarts, etc. PHP talks to the Gearmand server via an API extension Just like MySQL, Memcached, Postgresql, APC and other tools
  • 56. Gearmand runs as another daemon/service in your stack. Can be a different server or run along side everything else Gearman’s only job is to facilitate the handling of these messages It can optionally store them in a persistent store to recover from system reboots, service restarts, etc. PHP talks to the Gearmand server via an API extension Just like MySQL, Memcached, Postgresql, APC and other tools Your client and worker code pass messages back and forth to Gearman You’ll use a predefined set of PHP function calls to do this
  • 57. Getting Gearmand running - installers for many systems
  • 58. Getting Gearmand running - installers for many systems Linux: apt-get, yum etc sudo apt-get install gearmand sudo yum install gearmand
  • 59. Getting Gearmand running - installers for many systems Linux: apt-get, yum etc sudo apt-get install gearmand sudo yum install gearmand Windows: cygwin ...
  • 60. Getting Gearmand running - installers for many systems Linux: apt-get, yum etc sudo apt-get install gearmand sudo yum install gearmand Windows: cygwin ... OS X: ... Install a package manager: MacPorts, Homebrew sudo port install gearmand brew install gearmand Add a Virtual Machine that has an installer...
  • 61. Getting Gearmand running - compile your own
  • 62. Getting Gearmand running - compile your own Get your dependencies sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid- devel
  • 63. Getting Gearmand running - compile your own Get your dependencies sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid- devel Get the latest stable source from gearman.org (Launchpad) wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz
  • 64. Getting Gearmand running - compile your own Get your dependencies sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid- devel Get the latest stable source from gearman.org (Launchpad) wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz Unpack, Compile and Install tar -xzf gearmand-0.34.tar.gz cd gearmand-0.34.tar.gz ./configure make sudo make install
  • 65. Getting Gearmand running - compile your own Get your dependencies sudo yum install gpp gcc-c++ boost boost-devel libevent libevent-devel libuuid libuuid- devel Get the latest stable source from gearman.org (Launchpad) wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz Unpack, Compile and Install tar -xzf gearmand-0.34.tar.gz cd gearmand-0.34.tar.gz ./configure make sudo make install Add appropriate system hooks to start the service on reboot chkconfig systemctl ?
  • 67. Configuring Gearmand Default install is pretty good Load gearmand as a background service No persistence Listens on all available interfaces at port 4730
  • 68. Configuring Gearmand Default install is pretty good Load gearmand as a background service No persistence Listens on all available interfaces at port 4730 Persistence Easily enabled using MySQL based databases (Drizzle, MySQL, MariaDB etc) Postgresql SQL Lite Memcached Add the appropriate flags to your init script for details on each Docs: http://gearman.org/index.php?id=manual:job_server#persistent_queues Example: MySQL /sbin/gearmand -q libdrizzle --libdrizzle-host=127.0.0.1 --libdrizzle-user=gearman --libdrizzle-password=secret --libdrizzle-db=queue --libdrizzle-table=gearman --libdrizzle-mysql
  • 69. Configuring Gearmand Defaults to single thread (mostly) Some versions default to use more than one... Non-blocking I/O which works very fast with a single thread To give each of the internals a dedicated thread use /sbin/gearmand -d -t 3 Additional threads are then used for client worker connections
  • 70. Configuring Gearmand Defaults to single thread (mostly) Some versions default to use more than one... Non-blocking I/O which works very fast with a single thread To give each of the internals a dedicated thread use /sbin/gearmand -d -t 3 Additional threads are then used for client worker connections Security Lock gearmand to a single IP /sbin/gearmand -d -L 127.0.0.1 Change the port from the default 4730 /sbin/gearmand -d -L 127.0.0.1 -p 7003
  • 71. Configuring Gearmand Defaults to single thread (mostly) Some versions default to use more than one... Non-blocking I/O which works very fast with a single thread To give each of the internals a dedicated thread use /sbin/gearmand -d -t 3 Additional threads are then used for client worker connections Security Lock gearmand to a single IP /sbin/gearmand -d -L 127.0.0.1 Change the port from the default 4730 /sbin/gearmand -d -L 127.0.0.1 -p 7003 HTTP Access Gearmand supports a pluggable interface architecture and can use HTTP for communication. Requests are sent using GET and POST data.
  • 72. Configuring Gearmand for high availability
  • 73. Configuring Gearmand for high availability Gearmand doesn’t replicate data May be a weak point depending on your use case
  • 74. Configuring Gearmand for high availability Gearmand doesn’t replicate data May be a weak point depending on your use case Redundancy without a load balancer In the client logic, add multiple servers and let the driver sort it out Workers register themselves with each gearmand server Done.
  • 75. Configuring Gearmand for high availability Gearmand doesn’t replicate data May be a weak point depending on your use case Redundancy without a load balancer In the client logic, add multiple servers and let the driver sort it out Workers register themselves with each gearmand server Done.
  • 76. Configuring Gearmand for high availability Easy to load balance Put the two servers behind a load balancer Each client connects to the load balancer Workers register themselves with each gearmand server Done.
  • 77. Configuring Gearmand for high availability Easy to load balance Put the two servers behind a load balancer Each client connects to the load balancer Workers register themselves with each gearmand server Done.
  • 79. Adding Gearman API to PHP Package managers to the rescue again! sudo apt-get install php-pecl-gearman sudo yum install php-pecl-gearman
  • 80. Adding Gearman API to PHP Package managers to the rescue again! sudo apt-get install php-pecl-gearman sudo yum install php-pecl-gearman Pecl sudo pecl install gearman sudo echo “extension=gearman.so” > /etc/php.d/gearman.ini
  • 81. Adding Gearman API to PHP Package managers to the rescue again! sudo apt-get install php-pecl-gearman sudo yum install php-pecl-gearman Pecl sudo pecl install gearman sudo echo “extension=gearman.so” > /etc/php.d/gearman.ini Quick test php -i | grep “gearman support” gearman support => enabled
  • 82. Adding Gearman API to PHP Package managers to the rescue again! sudo apt-get install php-pecl-gearman sudo yum install php-pecl-gearman Pecl sudo pecl install gearman sudo echo “extension=gearman.so” > /etc/php.d/gearman.ini Quick test php -i | grep “gearman support” gearman support => enabled Restart any services with PHP resident in memory Apache, Nginx, etc
  • 83. Can we get to the code already?
  • 84. Gearman in PHP - The Client Clients create the jobs and tasks for the workers to do
  • 85. Gearman in PHP - The Client Clients create the jobs and tasks for the workers to do Create a client object $gm = new GearmanClient();
  • 86. Gearman in PHP - The Client Clients create the jobs and tasks for the workers to do Create a client object $gm = new GearmanClient(); Define the server(s) to use $gm->addServer(); // defaults to localhost:4730
  • 87. Gearman in PHP - The Client Clients create the jobs and tasks for the workers to do Create a client object $gm = new GearmanClient(); Define the server(s) to use $gm->addServer(); // defaults to localhost:4730 Create the job and wait for a response $jobdata = “/* any valid string */”; do { $res = $gm->do(‘image_resize’, $jobdata); } while ($gm->returnCode() != GEARMAN_SUCCESS);
  • 88. Gearman in PHP - The Client Clients create the jobs and tasks for the workers to do Create a client object $gm = new GearmanClient(); Define the server(s) to use $gm->addServer(); // defaults to localhost:4730 Create the job and wait for a response $jobdata = “/* any valid string */”; do { $res = $gm->do(‘image_resize’, $jobdata); } while ($gm->returnCode() != GEARMAN_SUCCESS); Or don’t $jobid = $gm->doBackground(‘image_resize’, $jobdata);
  • 89. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request
  • 90. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request Define the callbacks function callback_resize($job){ /* do stuff */ } function callback_watermark($job){ /* do stuff */ }
  • 91. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request Define the callbacks function callback_resize($job){ /* do stuff */ } function callback_watermark($job){ /* do stuff */ } Create a worker object $gm = new GearmanWorker();
  • 92. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request Define the callbacks function callback_resize($job){ /* do stuff */ } function callback_watermark($job){ /* do stuff */ } Create a worker object $gm = new GearmanWorker(); Define the server(s) to respond to $gm->addServer(); // defaults to localhost:4730
  • 93. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request Define the callbacks function callback_resize($job){ /* do stuff */ } function callback_watermark($job){ /* do stuff */ } Create a worker object $gm = new GearmanWorker(); Define the server(s) to respond to $gm->addServer(); // defaults to localhost:4730 Tell the server which callbacks to use for each task $gm->addFunction(‘resize’, ‘callback_resize’); $gm->addFunction(‘watermark’, ‘callback_watermark’);
  • 94. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request Define the callbacks function callback_resize($job){ /* do stuff */ } function callback_watermark($job){ /* do stuff */ } Create a worker object $gm = new GearmanWorker(); Define the server(s) to respond to $gm->addServer(); // defaults to localhost:4730 Tell the server which callbacks to use for each task $gm->addFunction(‘resize’, ‘callback_resize’); $gm->addFunction(‘watermark’, ‘callback_watermark’); Wait for work to do while($gm->work());
  • 95. Gearman in PHP - The Worker Workers do the jobs and tasks the clients request Define the callbacks function callback_resize($job){ /* do stuff */ } function callback_watermark($job){ /* do stuff */ } Create a worker object $gm = new GearmanWorker(); Define the server(s) to respond to $gm->addServer(); // defaults to localhost:4730 Tell the server which callbacks to use for each task $gm->addFunction(‘resize’, ‘callback_resize’); $gm->addFunction(‘watermark’, ‘callback_watermark’); Wait for work to do while($gm->work()); Callback functions can post status updates on their progress back to the client $job->setStatus($numerator/$denominator);
  • 96. Example Clients in CodeIgniter class Photos extends CI_Model { ! public function resize_sync($filename){ ! ! $gm = new GearmanClient(); ! ! $gm->addServer('127.0.0.1', 4730); ! ! do { ! ! ! $res = $gm->do('image_resize', $filename); ! ! ! switch($gm->returnCode()){ ! ! ! ! case GEARMAN_WORK_FAIL: ! ! ! ! ! return FALSE; ! ! ! ! case GEARMAN_SUCCESS: ! ! ! ! ! return TRUE; ! ! ! } ! ! } while ($gm->returnCode() != GEARMAN_SUCCESS);! ! return TRUE; ! } ! public function resize_async($filename){ ! ! $gm = new GearmanClient(); ! ! $gm->addServer('127.0.0.1', 4730); ! ! $res = $gm->doBackground('image_resize', $filename); if(!$res){ return FALSE; } ! return TRUE; ! } }
  • 97. The Callback Handlers class Photos extends CI_Model { ! public function resize_sync($filename){ /* ... */ } ! public function resize_async($filename){ /* ... */ } ! static public function image_resize($job){ ! ! $filename = $job->workload(); ! ! $CI =& get_instance(); ! ! $config = array( ! ! ! 'source_image' => $filename, ! ! ! 'create_thumbnail' => TRUE, ! ! ! 'maintain_ratio' => TRUE, ! ! ! 'width' => 800, ! ! ! 'height' => 600, ! ! ); ! ! $CI->image_lib->initialize($config); ! ! $CI->image_lib->resize(); ! ! $CI->image_lib->clear(); ! ! return true; ! } ! static public function image_watermark($job){ /* ... */ } }
  • 98. The Worker class Photos extends CI_Model { ! public function resize_sync($filename){ /* ... */ } ! public function resize_async($filename){ /* ... */ } ! static public function image_resize($job){ /* ... */ } ! static public function image_watermark($job){ /* ... */ } ! public function gearman_worker() ! {! ! ! ! $gm = new GearmanWorker(); ! ! $gm->addServer('127.0.0.1', 4730); ! ! $gm->addFunction('image_resize', 'Photos::image_resize'); ! ! $gm->addFunction('image_watermark', 'Photos::image_watermark'); ! ! while($gm->work()); ! } }
  • 99. Bringing it all together class Upload extends CI_Controller { ! function index(){ ! ! $this->load->model('photos'); ! ! $this->load->helper(array(‘url’)); ! ! $ul_config = array( /* ... */ ); ! ! $this->load->library(‘upload’, $ul_config); ! ! if($this->upload->do_upload()){ ! ! ! $file_info = $this->upload->data(); ! ! ! $this->photos->resize_async($file_info['full_path']); ! ! ! redirect(site_url(‘controller/next’)); ! ! } else { /* error handling code */ } ! } ! function worker(){ ! ! $this->load->model('photos'); ! ! $this->photos->gearman_worker(); ! } }
  • 100. Running your workers #!/bin/bash SCRIPT="index.php upload gearman_worker"! # this is your CI controller/method WORKDIR=/var/www/html/ ! ! ! # this is your CI app root MAX_WORKERS=5! ! ! ! # number of workers PHP=/usr/bin/php! ! ! ! # location of PHP on your system COUNT=0! ! ! ! ! # internal use variable for i in `ps -afe | grep "$SCRIPT" | grep -v grep | awk '{print $2}'` do ! COUNT=$((COUNT+1)) done if test $COUNT -lt $MAX_WORKERS then ! cd $WORKDIR ! $PHP $SCRIPT else ! echo There are enough workers running already. fi
  • 101. Demo Time: Image Resizing
  • 102. About the job data Job data is always a string
  • 103. About the job data Job data is always a string You can serialize data to pass more complex objects $data = array( ‘filename’ => $filename, ‘methods’ => array(‘resize’, ‘watermark’), ‘user_id’ => $user_id, ); $jobdata = json_encode($data); $gm->doBackground(‘processor’, $jobdata);
  • 104. About the job data Job data is always a string You can serialize data to pass more complex objects $data = array( ‘filename’ => $filename, ‘methods’ => array(‘resize’, ‘watermark’), ‘user_id’ => $user_id, ); $jobdata = json_encode($data); $gm->doBackground(‘processor’, $jobdata); And then deserialize it in the worker $jobdata = $job->workload(); $data = json_decode($jobdata, true);
  • 105. About the job data In theory, you can pass about 2Gb per message Limited by the server protocol which uses a 32 bit integer to define message size.
  • 106. About the job data In theory, you can pass about 2Gb per message Limited by the server protocol which uses a 32 bit integer to define message size. You can pass binary data by encoding it $binary_base64 = base64_encode($binary);
  • 107. About the job data In theory, you can pass about 2Gb per message Limited by the server protocol which uses a 32 bit integer to define message size. You can pass binary data by encoding it $binary_base64 = base64_encode($binary); But use it sparingly Any data passed is stored in memory and your persistent store (if enabled) and is likely on disk already Base 64 encoded data is roughly 1 1/2 times the size of the source data too Compressing the binary data first can help
  • 108. About the job data Don’t pass 2Gb objects
  • 109. About the job data Don’t pass 2Gb objects Keep your message data small, less than 64K is perfect Amazon’s SQS has a hard limit of 64K
  • 110. About the job data Don’t pass 2Gb objects Keep your message data small, less than 64K is perfect Amazon’s SQS has a hard limit of 64K Pass pointers instead Pass paths and filenames instead of files Pass cache keys instead of complex class objects that won’t deserialize right anyway
  • 111. About the job data Don’t pass 2Gb objects Keep your message data small, less than 64K is perfect Amazon’s SQS has a hard limit of 64K Pass pointers instead Pass paths and filenames instead of files Pass cache keys instead of complex class objects that won’t deserialize right anyway Gearman is not a data store!
  • 113. Analytics: Problem We wanted to provide near realtime analytics to our clients
  • 114. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google
  • 115. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location
  • 116. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good!
  • 117. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good! But Google has API limits for getting data out of Analytics
  • 118. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good! But Google has API limits for getting data out of Analytics Only a few thousand requests per day
  • 119. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good! But Google has API limits for getting data out of Analytics Only a few thousand requests per day Batching requests was good - but not ideal
  • 120. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good! But Google has API limits for getting data out of Analytics Only a few thousand requests per day Batching requests was good - but not ideal Data was only monthly, no daily, weekly breakdowns
  • 121. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good! But Google has API limits for getting data out of Analytics Only a few thousand requests per day Batching requests was good - but not ideal Data was only monthly, no daily, weekly breakdowns Still ended up taking weeks to gather a full month of data
  • 122. Analytics: Problem We wanted to provide near realtime analytics to our clients We liked the data we could scrape out of Google Networks Referrers Location so we did... for a while... and it was good! But Google has API limits for getting data out of Analytics Only a few thousand requests per day Batching requests was good - but not ideal Data was only monthly, no daily, weekly breakdowns Still ended up taking weeks to gather a full month of data We already had scraped a significant amount of Google data so any future collection would need to play nice with the existing data
  • 123. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics
  • 124. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel
  • 125. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that
  • 126. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that captures the current url, user agent, referrer and so on
  • 127. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that captures the current url, user agent, referrer and so on and embeds it as an image tag with a carefully crafted URL for the 1x1 tracking pixel /statistics/pixel/?ua=Mozilla%2F...
  • 128. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that captures the current url, user agent, referrer and so on and embeds it as an image tag with a carefully crafted URL for the 1x1 tracking pixel /statistics/pixel/?ua=Mozilla%2F... The pixel request is handled by CodeIgniter, which returns the image,
  • 129. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that captures the current url, user agent, referrer and so on and embeds it as an image tag with a carefully crafted URL for the 1x1 tracking pixel /statistics/pixel/?ua=Mozilla%2F... The pixel request is handled by CodeIgniter, which returns the image, but not before we lookup the country, state, city of the originating IP and pass that data into Gearman for future processing.
  • 130. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that captures the current url, user agent, referrer and so on and embeds it as an image tag with a carefully crafted URL for the 1x1 tracking pixel /statistics/pixel/?ua=Mozilla%2F... The pixel request is handled by CodeIgniter, which returns the image, but not before we lookup the country, state, city of the originating IP and pass that data into Gearman for future processing. The Gearman worker then parses and normalizes the data,
  • 131. Analytics: Solution Build our own platform that gathered exactly what we wanted modeled after Google Analytics How we did our tracking pixel The page has a small javascript file included that captures the current url, user agent, referrer and so on and embeds it as an image tag with a carefully crafted URL for the 1x1 tracking pixel /statistics/pixel/?ua=Mozilla%2F... The pixel request is handled by CodeIgniter, which returns the image, but not before we lookup the country, state, city of the originating IP and pass that data into Gearman for future processing. The Gearman worker then parses and normalizes the data, performs a host lookup on the source IP (which is often very slow) all before recording the result in our datastore.
  • 134. Patterns and Recipes One to one Workers can run in optimized environments for specific tasks Example: Using R, Matlab etc to run mathematic analysis and still use CI to for the front end Example: Run code on a different server to avoid CPU/disk/memory contention with Apache etc. Example: Run tools on Windows platforms like .NET components for generating word files.
  • 135. Patterns and Recipes One to one Workers can run in optimized environments for specific tasks Example: Using R, Matlab etc to run mathematic analysis and still use CI to for the front end Example: Run code on a different server to avoid CPU/disk/memory contention with Apache etc. Example: Run tools on Windows platforms like .NET components for generating word files. One to many A single client can part out jobs to multiple workers Example: Performing TF*IDF analysis on documents to find keywords Example: Handling image manipulations in parallel, resizing 2 or 3 new thumbnails at a time.
  • 136. Patterns and Recipes Many to one Multiple clients utilizing a single worker thread Share memory across jobs. Arrays are faster than APC, Memcached, MySQL Example: Database write buffering (for non critical data only) Example: Perform database writes across shards. MySQL UDF inserts a record into gearman that’s then re-written out to appropriate user shards
  • 137. Patterns and Recipes Many to one Multiple clients utilizing a single worker thread Share memory across jobs. Arrays are faster than APC, Memcached, MySQL Example: Database write buffering (for non critical data only) Example: Perform database writes across shards. MySQL UDF inserts a record into gearman that’s then re-written out to appropriate user shards Optimize front end displays Example: Pagination optimization User requests the first page of data Kick off a background task to pre-cache the next page before it’s requested Example: Dashboards User logs into your site, you fire off background tasks to generate dashboard information that user will need Workers begin crunching the data and store the results in a cache Meanwhile, the user is served a page with spaces allocated for each widget, which are then loaded via AJAX
  • 138. Patterns and Recipes Delayed/Deferred Processing Use whenever tasks would run long or are potentially unreliable Preparing images Preparing video Remote service calls Sending content to Twitter, Facebook, LinkedIn... Triggering other remote services faxes, emails etc Prefetching data
  • 140. Other Solutions Most alternative solutions have APIs for PHP Some interface over other protocols like HTTP(s) or memcache, which can ease deploying new servers
  • 141. Other Solutions Most alternative solutions have APIs for PHP Some interface over other protocols like HTTP(s) or memcache, which can ease deploying new servers Alternatives Active MQ Amazon’s SQS Beanstalkd Microsoft Message Queuing RabbitMQ Others - check for activity before adopting
  • 142. Some helpful tips Not everything belongs in a work queue
  • 143. Some helpful tips Not everything belongs in a work queue Queue it if...
  • 144. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc
  • 145. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler.
  • 146. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler. you want the benefit of running in parallel
  • 147. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler. you want the benefit of running in parallel Don’t use your database server as your work queue
  • 148. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler. you want the benefit of running in parallel Don’t use your database server as your work queue It might work short term, but it’s not scaleable.
  • 149. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler. you want the benefit of running in parallel Don’t use your database server as your work queue It might work short term, but it’s not scaleable. Persistence comes with a cost
  • 150. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler. you want the benefit of running in parallel Don’t use your database server as your work queue It might work short term, but it’s not scaleable. Persistence comes with a cost Writes to the datastore are never free and will slow down the queue
  • 151. Some helpful tips Not everything belongs in a work queue Queue it if... the process is intensive on any subsystem, CPU, RAM etc the process is slow, taking 1/2 second or longer to run, profile your app with CodeIgniter’s built-in profiler. you want the benefit of running in parallel Don’t use your database server as your work queue It might work short term, but it’s not scaleable. Persistence comes with a cost Writes to the datastore are never free and will slow down the queue Adds an additional layer of stuff to maintain

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n