Amazon SQS,分布式作业不再费心

By IceskYsl@1sters!


开始写这个之前,我不得不佩服下Amazon,不用说别的,就其SimpleDB,S3,EC2这几个就足以让业界大为惊叹,这些都比较熟悉了,今天说的是另外一个类似的东西,Amazon Simple Queue Service(SQS)。

看名字,大概就可以猜出大概的意思了,对,就是队列服务,SQS就是一个简单的队列服务,你可以创建一个队列,然后从不同的地方往里面东西,然后又可以在不同的地方不停的往外东西,想想看,这不就是分布式协作么。

但是需要注意的是,往里面放的时候,消息必须是txet,也就是是说不能放Hash或者数组啥的,如果您有类似需求,请接着往后看,我将提供一个变通的方法。

一、简介SQS

Amazon Simple Queue Service (Amazon SQS) offers a reliable, highly scalable, hosted queue for storing messages as they travel between computers. By using Amazon SQS, developers can simply move data between distributed components of their applications that perform different tasks, without losing messages or requiring each component to be always available.

二、如何使用

Ruby的社区足够活跃,每个应用都能找到对应的Gem或者插件,这给了我们足够的方便,针对SQS,我推荐的两个gem,分别是:

1、SQS Gem

这个插件是Amazon SQS官方站点写的教程《Using Amazon S3, EC2, SQS, Lucene, and Ruby for Web Spidering》上使用的,足够的简单,但是其主页貌似访问不了了,只能通过Google Cach看看。

使用非常方便,流程如下

1)安装:gem install SQS

2)测试:ruby test/all_tests.rb

3)使用示例

Ruby代码
  1. require 'rubygems'  
  2. require 'sqs'  
  3.   
  4. SQS.access_key_id = 'YOURACCESSKEYID'  
  5. SQS.secret_access_key = 'YOURSECRETACCESSKEY'  
  6.   
  7. q = SQS.create_queue 'myFantasticQ'  
  8. puts q.url  
  9.   
  10. SQS.each_queue do |q|  
  11.   puts q.name  
  12. end  
  13.   
  14. q = SQS.get_queue 'myFantasticQ'  
  15.   
  16. q.send_message 'This is a message!'  
  17.   
  18. m = q.receive_message  
  19. puts m.body  
  20. m.delete  
  21.   
  22. q.each_message do |m|  
  23.   # note that #each_message is an infinite loop!  
  24.   # you must either break out of it, or delete each message you receive  
  25.   m.delete  
  26. end  
  27.   
  28. q.approximate_number_of_messages  
  29. q.visibility_timeout  
  30. q.visibiltit_timeout = 3  
  31.   
  32. q.delete  

其他文章,可以自己Google。

2、RightScale gems

RightScale gemsRightScale 从其产品里面提取出来的,这个现象很常见,就像Shopify 中提取的Active Merchant一样,从一个成熟的产品中提取出来一个gem,其可用性是相当高的。

使用方法大同小异,不再赘述,如果感兴趣,请到上面的地址上自行查看。

三、如何扩展

前面我们说了,SQS中容纳的消息是text的,但是看其文档表述,是这样写的:

New messages can be added to a queue at any time. The message body can contain up to 8 KB of text in any format.

any time?啥意思?奇怪。

我认为一种可行的办法是,把Hash转成ymal格式的(.to_yaml),然后放进去后;取出的时候,直接YAML.load(message.body),然后再还原即可了。

看段代码,如下:

Ruby代码
  1. require 'SQS'  
  2. class Tsqs  
  3. SQS.conf_file = 'sqs_conf.yml'  
  4. s = SQS.new  
  5. puts s.api_version  
  6. puts s.conf_file  
  7. puts s.url_for_query  
  8. iceskysl = s.get_queue('iceskysl_message')  
  9. books_to_update = { 'bookid'=>"1",'url'=>"url1",'queue'=>"queue1"}  
  10. iceskysl.send_message(books_to_update.to_yaml)  
  11.   
  12. iceskysl_messages = iceskysl.receive_messages  
  13. puts iceskysl_messages.size  
  14. iceskysl_messages.each do |message|  
  15.  params = YAML.load(message.body)  
  16.  puts "bookid=" + params[:bookid] + ",url=" + params[:url] +  ",queue=" + params[:queue]  
  17.   message.delete  
  18. end  
  19. end  

看明白了么,没问题吧,呵呵。另外,这里还有一篇文章使用的是RightScale gems。

OK,差不多介绍完了,有疑问或者有其他好的gem请告诉我,谢谢。

参考文档:

  1. SQS API:http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148&categoryID=102
  2. SQS 主页:http://www.amazon.com/Simple-Queue-Service-home-page/b/ref= sc_fe_l_2/102-6256901-8077705?ie=UTF8&node=13584001&no=3435361&me=A36L942TSJ2AJA