Resque
High-performance asynchronous task queuing and
                  processing
Resque
High-performance asynchronous task queuing and
                  processing
Resque
High-performance asynchronous task queuing and
                  processing
Experts
Experts
‘Cause you might build the next GitHub
Three Things
1. Background
Why run background processes at all?
2. Delayed::Job
Because it’s the foundation for Resque
3. Resque
Process different.
1. Background

   Why?
1. Background

It’s all about the ms
1. Background

    It’s all about the ms
• Resize an image
1. Background

    It’s all about the ms
• Resize an image
• Send an e-mail
1. Background

    It’s all about the ms
• Resize an image
• Send an e-mail
• Communicate with a web service
1. Background

    It’s all about the ms
• Resize an image
• Send an e-mail
• Communicate with a web service
• Geocode a location
1. Background

Do something later
    than now
1. Background
1. Background

 Webpages.
1. Background

       Webpages.
Rails serves webpages.
                     Memories. You're
                      talkin about
                       memories.
1. Background
1. Background

1. Receive requests
1. Background

1. Receive requests
 2. Send responses
1. Background

Everything else can go
      elsewhere
1. Background

  Where?
1. Background

         Where?
• CRON
1. Background

               Where?
• CRON
• Beanstalkd
1. Background

               Where?
• CRON
• Beanstalkd
• Workling
1. Background

           Where?
• CRON
• Beanstalkd
• Workling
• BackgroundRB
1. Background

WTF my tasks r fail?!1
1. Background

WTF my tasks r fail?!1
• Silent failure
1. Background

WTF my tasks r fail?!1
• Silent failure
• No status checks
1. Background

WTF my tasks r fail?!1
• Silent failure
• No status checks
• Unstable processes
2. Delayed::Job

To the rescue!
2. Delayed::Job

To the rescue!
2. Delayed::Job

ActiveRecord::Base’d
2. Delayed::Job

 ActiveRecord::Base’d

• Persistence! At last!
2. Delayed::Job

 ActiveRecord::Base’d

• Persistence! At last!
• Ease of use! At last!
2. Delayed::Job

 How easy?
2. Delayed::Job

            Super easy.
# without delayed_job
Notifier.deliver_signup(@user)

# with delayed_job
Notifier.send_later :deliver_signup, @user
2. Delayed::Job

Where do they go?
2. Delayed::Job
mysql> SELECT * FROM delayed_jobs;
*************************** 1. row ***************************
        id: 1
  priority: 0
  attempts: 0
   handler: --- !ruby/object:WorkerBee <-- Notice the pretty Marshal dump
n: 18

last_error: NULL
    run_at: 2010-03-10 22:44:30
 locked_at: NULL
 failed_at: NULL
 locked_by: NULL
created_at: 2010-03-10 22:44:30
updated_at: 2010-03-10 22:44:30
1 row in set (0.00 sec)
2. Delayed::Job

What do you do with
      them?
2. Delayed::Job

  What do you do with
        them?
$ script/delayed_job start
2. Delayed::Job

     Workers.
2. Delayed::Job

     Workers.
    • Live in their own thread
2. Delayed::Job

     Workers.
    • Live in their own thread
    • Query the database for jobs
2. Delayed::Job

     Workers.
    • Live in their own thread
    • Query the database for jobs
    • Perform the long-running task
      away from request/response
The Old Way
The New Way


Delayed::Job
2. Delayed::Job


 Totally rad.
3. Resque

Isn’t Delayed::Job
      enough?
3. Resque

Isn’t Delayed::Job
      enough?
3. Resque


Apparently not.
3. Resque

   Resque is some
Enterprise Grade shit.
3. Resque


Runs on Redis
3. Resque


Runs on Redis
Tangent Alert: Redis!

Redis is a Key-Value
        Store
      Just like Memcached
Tangent Alert: Redis!

    Persistence
      Unlike Memcached
Tangent Alert: Redis!

               Scalability
           The Gem load balances for you


Resque.redis = DistRedis.new(
  :hosts=> %w{192.168.1.22:6379 192.168.1.23:6379}
)
Tangent Alert: Redis!

      Basically:
 Fast & Distributed
Tangent Alert: Redis!

Also, Rails-independent
No ActiveRecord/ActiveSupport means you can run
Resque (on Redis) in Sinatra or any other Ruby app
3. Resque

Better Workers
3. Resque

      Better Workers
• Forked, sandboxed threads
3. Resque

      Better Workers
• Forked, sandboxed threads
• Failing tasks are tracked
3. Resque

      Better Workers
• Forked, sandboxed threads
• Failing tasks are tracked
• Kills timeouts
3. Resque

                 Queueing
          Separate queues for separate workers



fileserver$ QUEUE=zip_files rake resque:work
 webserver$ QUEUE=cache_images rake resque:work
3. Resque

         No Marshaling
          Because it should be functional



Resque.enqueue(SignupNotifier, @user.id)
3. Resque

         No Marshaling
class SignupNotifier
  def self.perform(user_id)
    Notifier.deliver_signup(User.find(user_id))
  end
end
3. Resque

                UI
That’s right. It has its own interface.
3. Resque

So... why?
3. Resque

           So... why?
• Many background tasks
3. Resque

            So... why?
• Many background tasks
• Distributed task servers
3. Resque

            So... why?
• Many background tasks
• Distributed task servers
• Stable workers
3. Resque

Trouble Points
3. Resque

      Trouble Points
• Complex and expensive
3. Resque

        Trouble Points
• Complex and expensive
• No scheduling or priority like in D::J
3. Resque

       Trouble Points
• Complex and expensive
• No scheduling or priority like in D::J
• Asynchronous Redis writes don’t guarantee
  persistence
3. Resque

Live coding FTW!
    Here goes nothing...
Thnaks
Thanks for taking the time to listen to me blather
                 about Resque!
Me!
  Github:    http://github.com/flipsasser
Homepage:    http://x451.com
  Twitter:   @flipsasser
   E-mail:   flip@intridea.com
Bmore on Rails

  Meetups - 2nd Tuesday
  #OSHN - 4th Tuesday

http://www.meetup.com/bmore-on-rails/

Asynchronous Awesome

Editor's Notes

  • #2 Okay, my talk is called &amp;#x201C;...&amp;#x201D; which I think is pretty descriptive. Except that it doesn&amp;#x2019;t really demonstrate the pure awesome is that is Resque, so really, we&amp;#x2019;ll call it...
  • #3 Yeah.
  • #4 So, why should you care about what I&amp;#x2019;m going to say in the next 20 minutes? Because when you walk away from this room, you&amp;#x2019;ll all be experts at building a network of high-performance and fault-tolerant workers.
  • #5 So we&amp;#x2019;re going to talk about three things today
  • #6 First, we&amp;#x2019;re going to do a general background of background processing
  • #7 Next, we&amp;#x2019;ll cover the basic concepts of Resque that are derived from Delayed::Job
  • #8 Last, we&amp;#x2019;ll get into Resque, and how it&amp;#x2019;s different.
  • #9 So, why run background tasks at all?
  • #10 - Resize - Etc That&amp;#x2019;s all really cool stuff, but it all takes time - sometimes a few seconds, sometimes up to 30 seconds. So, someone, somewhere, had an idea:
  • #11 - Resize - Etc That&amp;#x2019;s all really cool stuff, but it all takes time - sometimes a few seconds, sometimes up to 30 seconds. So, someone, somewhere, had an idea:
  • #12 - Resize - Etc That&amp;#x2019;s all really cool stuff, but it all takes time - sometimes a few seconds, sometimes up to 30 seconds. So, someone, somewhere, had an idea:
  • #13 - Resize - Etc That&amp;#x2019;s all really cool stuff, but it all takes time - sometimes a few seconds, sometimes up to 30 seconds. So, someone, somewhere, had an idea:
  • #14 Let&amp;#x2019;s do something later than now. If my application doesn&amp;#x2019;t NEED to do this stuff right away, don&amp;#x2019;t keep the request tied up. After all, what IS a request for?
  • #15 Webpages In case you&amp;#x2019;d forgotten - Rails serves webpages. It&amp;#x2019;s not built to process images or send out mass e-mails; it&amp;#x2019;s built to do two things:
  • #16 Webpages In case you&amp;#x2019;d forgotten - Rails serves webpages. It&amp;#x2019;s not built to process images or send out mass e-mails; it&amp;#x2019;s built to do two things:
  • #17 Webpages In case you&amp;#x2019;d forgotten - Rails serves webpages. It&amp;#x2019;s not built to process images or send out mass e-mails; it&amp;#x2019;s built to do two things:
  • #18 Webpages In case you&amp;#x2019;d forgotten - Rails serves webpages. It&amp;#x2019;s not built to process images or send out mass e-mails; it&amp;#x2019;s built to do two things:
  • #19 - Receive requests - Send responses
  • #20 - Receive requests - Send responses
  • #21 Everything else can go elsewhere
  • #22 So... where should it go? There are a whole bunch of options. - CRON - Etc. But sometimes those setups have problems
  • #23 So... where should it go? There are a whole bunch of options. - CRON - Etc. But sometimes those setups have problems
  • #24 So... where should it go? There are a whole bunch of options. - CRON - Etc. But sometimes those setups have problems
  • #25 So... where should it go? There are a whole bunch of options. - CRON - Etc. But sometimes those setups have problems
  • #26 - They can fail without telling you why - You can&amp;#x2019;t get the status of one of a worker - Ruby processes can be unstable and crash-ey So maybe you need something a little bit better
  • #27 - They can fail without telling you why - You can&amp;#x2019;t get the status of one of a worker - Ruby processes can be unstable and crash-ey So maybe you need something a little bit better
  • #28 - They can fail without telling you why - You can&amp;#x2019;t get the status of one of a worker - Ruby processes can be unstable and crash-ey So maybe you need something a little bit better
  • #29 Delayed::Job to the rescue!
  • #30 A Delayed::Job is an ActiveRecord model, so it lives in the database. - You get persistence baked right in - It&amp;#x2019;s unbelievably easy to use
  • #31 A Delayed::Job is an ActiveRecord model, so it lives in the database. - You get persistence baked right in - It&amp;#x2019;s unbelievably easy to use
  • #32 How easy?
  • #33 Super easy. I pulled this straight from the github page. This code shows how you would create a Delayed::Job
  • #34 But where does that job go?
  • #35 Here - your database. Notice that it simply marshals the object and stuffs in the database.
  • #36 So what do you do with these jobs in the database? - Run the delayed_job script This will create...
  • #37 Workers. They&amp;#x2019;re separate Ruby processes that - Live in their own thread - Find jobs in the database - Perform them separately from the request/response cycle They boot up your Rails environment to do so.
  • #38 Workers. They&amp;#x2019;re separate Ruby processes that - Live in their own thread - Find jobs in the database - Perform them separately from the request/response cycle They boot up your Rails environment to do so.
  • #39 Workers. They&amp;#x2019;re separate Ruby processes that - Live in their own thread - Find jobs in the database - Perform them separately from the request/response cycle They boot up your Rails environment to do so.
  • #40 So before, you had requests coming from a browser into Rails, which dispatches to various services, gets results, and sends something back to the browser
  • #41 Now you have Rails storing the jobs for later, and Delayed::Job comes along and does the processing Rails isn&amp;#x2019;t good at doing anyway.
  • #42 So Delayed::Job is totally rad. It handles most of what you might want it to handle.
  • #43 So when we start in with Resque, you might wonder, &amp;#x201C;Isn&amp;#x2019;t Delayed::Job enough?&amp;#x201D;
  • #44 Apparently not. There are some situations where Delayed::Job isn&amp;#x2019;t sufficient.
  • #45 Basically, Resque is enterprise grade shit.
  • #46 So the first big difference between Resque and Delayed::Job is that Resque doesn&amp;#x2019;t rely on ActiveRecord. It runs on something called Redis, which probably deserves - its own tangent
  • #47 Redis is an in-memory Key-Value Store similar to Memcached. But it offers
  • #48 Redis is an in-memory Key-Value Store similar to Memcached. But it offers
  • #49 Redis is an in-memory Key-Value Store similar to Memcached. But it offers
  • #50 Redis is an in-memory Key-Value Store similar to Memcached. But it offers
  • #51 Redis is an in-memory Key-Value Store similar to Memcached. But it offers
  • #52 Redis is an in-memory Key-Value Store similar to Memcached. But it offers
  • #53 Persistence! So you can reboot your server and Redis will reload your original queued jobs. It also is great at
  • #54 Scalability! The Ruby gem will load-balance tasks across multiple Redis servers for you, meaning you spend less time configuring and more time queueing
  • #55 So Redis makes Resque incredibly fast and easily distributed.
  • #56 Also, using Redis means you don&amp;#x2019;t have to worry about ActiveRecord - so you can skip Rails entirely
  • #57 The next big difference is Resque&amp;#x2019;s workers - When a worker finds a job to process, it creates a fork that it can monitor to process the job If a fork spirals out, it doesn&amp;#x2019;t take the worker with it - Workers are capable of moving failed jobs into the failed List and moving on with their lives - Workers are also capable of timing their own processes out and failing them
  • #58 The next big difference is Resque&amp;#x2019;s workers - When a worker finds a job to process, it creates a fork that it can monitor to process the job If a fork spirals out, it doesn&amp;#x2019;t take the worker with it - Workers are capable of moving failed jobs into the failed List and moving on with their lives - Workers are also capable of timing their own processes out and failing them
  • #59 The next big difference is Resque&amp;#x2019;s workers - When a worker finds a job to process, it creates a fork that it can monitor to process the job If a fork spirals out, it doesn&amp;#x2019;t take the worker with it - Workers are capable of moving failed jobs into the failed List and moving on with their lives - Workers are also capable of timing their own processes out and failing them
  • #60 Resque also supports queues, so different types of tasks can be divided by disparate workers. A file server, for example, can have a worker that only zips files - while a web server can warm image caches.
  • #61 Resque also skips the marshaling step, and instead opts for a class and a JSON-ifiable argument list. This will keep all instances current
  • #62 The class&amp;#x2019; &amp;#x201C;perform&amp;#x201D; method is called with the arguments you enqueued it with
  • #63 Resque comes with its own interface for monitoring queues and tasks, and reviewing failed tasks.
  • #64 So why use Resque? Use Resque if - You have many, many, many background tasks - You need to have different servers performing different types tasks - You need bullet-proof workers
  • #65 So why use Resque? Use Resque if - You have many, many, many background tasks - You need to have different servers performing different types tasks - You need bullet-proof workers
  • #66 So why use Resque? Use Resque if - You have many, many, many background tasks - You need to have different servers performing different types tasks - You need bullet-proof workers
  • #67 Trouble - Complex / expensive - No scheduling or priority - Asynchronous Redis writes don&amp;#x2019;t guarantee persistence
  • #68 Trouble - Complex / expensive - No scheduling or priority - Asynchronous Redis writes don&amp;#x2019;t guarantee persistence
  • #69 Trouble - Complex / expensive - No scheduling or priority - Asynchronous Redis writes don&amp;#x2019;t guarantee persistence
  • #70 Okay, if we have time I&amp;#x2019;ll show off Resque&amp;#x2019;s UI and do a quick comparison of it to D::J
  • #71 Thanks for listening!
  • #72 This is me - you can find me on Github or Twitter, and if you&amp;#x2019;re interested I&amp;#x2019;ll post these slides on Twitter.
  • #73 Last but not least, I&amp;#x2019;m a visiting emissary from B&amp;#x2019;more on Rails, and I&amp;#x2019;d like to personally invite all of you to come up to our Meetups (on the 2nd tuesday of every month) and our Open Source Hack Nights (on the 4th Tuesday of every month).