cloudpack の 自称 Sensu芸人 の かっぱこと 川原 洋平@inokara)です。

お詫び

以前にアップしていた記事を手違いにより削除してしまいましたので、改めてアップ致しました。

はじめに

AWS 白帯シリーズ第四弾として前回前々回に引き続き SQS を取り扱っていきたいと思います。

今回は AWS SDK for Ruby と AWS CLI から SNS から届いたメッセージを取り出してみたいと思います。


準備するもの

白帯とは言え、上記のツールは道着のようなものですので道場に入る前に準備しておきましょう。

AWS SDK for Ruby

Ruby が既にインストールされていてる環境にて以下を実行します。

gem install aws-sdk

Ruby のバージョン(古いバージョン)によっては依存モジュールの関係でインストールに苦労することがありますので詳しくは上記リンク先を御覧ください。

AWS CLI

Python pip を利用してインストールします。

pip install awscli

乱取り

細かい説明はこちらの神資料にお任せして、コマンドやコードを一気に載っけていこうと思います。その名も乱取り

キューの一覧を取得する

全て以下のような結果が返ってくることを期待します。

https://sqs.us-east-1.amazonaws.com/123456789012/first-queue

又は

https://queue.amazonaws.com/123456789012/first-queue

前者は AWS SDK for Ruby で得られる結果、後者は AWS CLI で得られる結果です。これらの結果を得たい場合にはそれぞれ以下ようなスクリプト又はコマンドを実行します。

AWS SDK for Ruby
#!/usr/bin/env ruby

require 'aws-sdk'

AWS.config(
  :access_key_id => 'AKxxxxxxxxxxxxxxxxxx',
  :secret_access_key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
)

sqs = AWS::SQS.new

puts sqs.queues.collect(&:url)
AWS CLI
aws sqs list-queues --query 'QueueUrls[*]' --output text

メッセージを取り出す

まずは Message ID だけを取り出しましょう。以下のような結果が返ってくることを期待します。

12345678-1234-1234-1234-123456789012

ここで…一点だけうんちくポイント。同じメッセージを二つのクライアントから取り出せてしまうようなことがあると困りますよね。このお困りポイントを解決する方法として以下の二点があります。

  • メッセージを削除する
  • Default Visibility Timeout を設定して一度取り出されたメッセージは一定期間見えないようにする

Default Visibility Timeout については以下のようにして AWS CLI から確認することが可能です。

aws sqs get-queue-attributes --queue-url https://queue.amazonaws.com/1234567890123/first-queue --attribute-names VisibilityTimeout --query 'Attributes.VisibilityTimeout' --output text

マネジメントコンソールからは以下のように確認出来ます。

01

特に設定を弄っていない場合には 30 秒が設定されています。

AWS SDK for Ruby
#!/usr/bin/env ruby

require 'aws-sdk'

AWS.config(
  :access_key_id => 'AKxxxxxxxxxxxxxxxxxx',
  :secret_access_key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
)

sqs = AWS::SQS.new
sqs.queues.collect(&:url).each do |url|
  puts url
  receive = sqs.queues[url].receive_message()
  if receive != nil
    puts receive.id
  end
end
AWS CLI
aws sqs receive-message --queue-url https://queue.amazonaws.com/1234567890123/first-queue --query 'Messages[*].MessageId' --output text

メッセージを取り出す(2)

次にメッセージの内容を取り出したいと思います。メッセージの内容は body と呼ばれるインスタンス属性に JSON 形式で入っていますので JSON を解析する必要があるのが注意点です。ということでメッセージの内容(body)からタイトル(Subject)を取り出してみたいと思います。期待する結果は…

"こんにちわ"

です。

AWS SDL for Ruby
#!/usr/bin/env ruby

require 'aws-sdk'

AWS.config(
  :access_key_id => 'AKxxxxxxxxxxxxxxxxxx',
  :secret_access_key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
)

sqs = AWS::SQS.new
sqs.queues.collect(&:url).each do |url|
  puts url
  receive = sqs.queues[url].receive_message()
  if receive != nil
    b = JSON.parse(receive.body)
    p b['Subject']
  end
end

解析された JSON はハッシュ化された状態で変数 b に入りますので、キーの Subject を指定して取り出してあげます。

AWS CLI

AWS CLI でこれをやろうとすると苦戦し(てます)。メッセージの Body には SNS から届いたメッセージが JSON 形式で入っているのですが、以下のように実行すると Body 部分の JSON がエスケープされた状態で出力されてしまいます…がびーん。

aws sqs receive-message --queue-url https://queue.amazonaws.com/123456789012/first-queue --query 'Messages[*].Body' | tee hoge

以下、がびーんな図です。

02


違うアプローチ

SQS のキューからメッセージを取り出す為のアプローチとして、同じ SDK を使いつつより簡単に出来る方法として fluentd とプラグイン を組み合わせてメッセージを取り出すことが出来ますので以下に紹介します。

td-agent のインストール

fluentd と言っておきながら td-agent を利用します。

curl -L http://toolbelt.treasuredata.com/sh/install-redhat.sh | sudo sh

fluent-plugin-sqs のインストールと設定

fluent-plugin-sqs をインストールします。

インストール

sudo /usr/lib64/fluent/ruby/bin/gem install fluent-plugin-sqs --no-ri --no-rdoc -V

設定

今回は in_sqs プラグインを利用します。

<source>
  type sqs
  #
  aws_key_id AKxxxxxxxxxxxxxxxxxx
  aws_sec_key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  sqs_url https://sqs.ap-northeast-1.amazonaws.com/123456789012/kappa-test
  #
  sqs_endpoint sqs.ap-northeast-1.amazonaws.com
  #
  receive_interval 60
  #
  tag your_tag
</source>

<match your_tag.**>
  type stdout
</match>

とりあえず上記の設定で /var/log/td-agent/td-agent.log にキューに蓄積されたメッセージが以下のように出力されました。

03

頑張って Ruby で書くより百万倍(当社比)簡単ですね!


まだまだ

続くよー。

元記事は、こちら