2014-08-29 71 views
1

最近我一直在做很多Sinatra,我认为是时候把它带到下一个级别。任何帮助将很乐意欣赏球员。所以这就是我正在考虑的:每当Amazon SQS队列更新时运行Ruby任务

应用程序A在用户发出事件时将事件引发到Amazon SQS队列。无论何时将任何事件引入队列,应用程序B都会执行一项任务(例如,发送带有“嗨”消息的电子邮件用户)。我从来没有真正与Cron作业等工作的下面的代码:

$sum = 1 

Thread.new do # trivial example work thread 
    while true do 
    sleep 3 
    $sum += 1 
    end 
end 


get '/' do 
    "Testing background work thread: sum is #{$sum}" 
end 

感谢马克沃森这个(http://markwatson.com/blog/2011-11/ruby-sinatra-web-apps-with-background-work-threads.html

这里是我的疑惑:

  • 就是“做任务在亚马逊队列更新“可能吗?或者我认为这是错误的方式?
  • 如何更新上述代码,使其每3秒自动刷新一次而不发生“无限循环”错误?

回答

2

我建议你把你的应用程序分成两部分。一个是常规Sinatra网络应用程序,另一个是某种背景工作者。

示例应用程序

这是简单不以生产工作的例子,你可以使用。

创建一些常见的boot.rb文件,你把你的“初始化”代码:

require 'bundler/setup' 

# Use this to load my '.env' that contains AWS credentials 
require 'dotenv'; Dotenv.load 

# We are using Amazon Ruby SDK 
require 'aws-sdk' 

# We configure AWS Ruby SDK 
AWS.config(
    access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'), 
    secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY') 
) 

# We get SQS Web Service 
sqs = AWS::SQS.new 

QUEUE = sqs.queues[ENV.fetch('AWS_QUEUE_URL')] 

简单西纳特拉网络app.rb,如果你访问发送消息哟您的Amazon SQS /烟。

require_relative 'boot' 
require 'sinatra' 

get '/smoke' do 
    message = QUEUE.send_message({email: "[email protected]", at: DateTime.now}.to_json.to_s) 
    "Message was sent to Amazon SQS with id #{message.id}.\n" 
end 

创建另一个文件 - 它命名为worker.rb - 这将订阅您的Amazon SQS队列和下拉消息。

require_relative 'boot' 

QUEUE.poll do |msg| 
    object = JSON.load(msg.body) rescue {} 
    puts "Got your email #{object['email']} at #{object['at']}." 
end 

我的地方.ENV文件包含证书和URL给SQA队列。

AWS_ACCESS_KEY_ID=secret 
AWS_SECRET_ACCESS_KEY=secret 
AWS_QUEUE_URL=https://sqs.us-west-1.amazonaws.com/... 

运行它

然后你只需启动你的Sinatra应用和工人,像这样

ruby app.rb # in one terminal 
ruby worker.rb # in another terminal 

如果你再访问/smoke,你会看到这样的事情 - 这意味着作业调度。

Message was sent to Amazon SQS with id 788e5e28-8055-4c8f-bb51-c634c327a021. 

而且在你的工人终端你会看到

Got your email [email protected] at 2014-08-29T15:20:38+02:00. 

现在,你不必限制自己只是一个工人......你可以有像你一样多,一个消息将仅在一个工作人员处理,默认情况下。另一个需要注意的是,我们正在发送JSON作为消息,这就是为什么我在worker中使用了JSON.load。 Amazon SQS发送/接收纯文本消息。

1

我建议你看看Shoryuken,它位于AWS SDK之上。您可以轻松地与Sinatra或任何其他Ruby应用程序集成。

get '/' do 
    MyWorker.perform_async(msg) 
end