cloudpack の 自称 Sensu芸人 の かっぱこと 川原 洋平(@inokara)です。
はじめに
Sensu について調べてて気になった点をメモしたいと思います。あくまでもメモですので内容につきましてはご自身でご確認いただければ幸いです。
脱 RabbitMQ 依存?
ドキュメントのアーキテクチャ図が変わった
Sensu ファンの皆さんならすでにお気づきのことかと思いますが、ドキュメントの Overview に以前掲載されていたアーキテクチャ図が更新されています。
以前のアーキテクチャ図は以下のような図だったと記憶しております。この図は個人的には Sensu のアーキテクチャを説明するには若干説明不足感は否めませんでした。
最新のアーキテクチャ図は以下のような GIF アニメーションにまでなっておりとても解りやすい図になっている気がします。
http://sensuapp.org/docs/0.12/overview より引用
基本的には RabbitMQ を監視キューのキューイングサービスとして、一見はアーキテクチャとして変わりはないように見えますが State と Transport という名前で各コンポーネントを分類している点が変わったポイントでとても興味深い書き方かと思っています。
勝手にイメージ
アーキテクチャ図に追加された State や Transport の記述から推測すると Sensu の各コンポーネントを役割毎に抽象化してそれぞれの役割で Redis や RabbitMQ 以外のツールでも置き換えられるような方向で開発を進めていこうとする作者の方々の意向を感じられます。
ただ、これはあくまでも個人的なイメージですので、「そんなんことは無い」ってツッコミをうけそうな気がしますが Sensu の良さはまさにコノ部分ではないかと思ったりしているので今後にとても期待しているところです。はい。
ソースコード探訪
で、上記の図を見る前から sensu のソースコード内から RabbitMQ に特化(AMQP に特化)した記述が無くなったなーって思っていたら transport というインスタンス変数を呼ぶような作りに変わっていました。その transport は以下の sensu-transport という Gem を require して利用するようです。
sensu-transport のソースツリーは以下のような構成になっていました。
sensu-transport
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── lib
│ └── sensu
│ ├── transport
│ │ ├── base.rb
│ │ └── rabbitmq.rb
│ └── transport.rb
├── sensu-transport.gemspec
└── spec
├── base_spec.rb
├── helpers.rb
├── rabbitmq_spec.rb
└── transport_spec.rb
4 directories, 12 files
ここで興味深いのが sensu-transport/lib/sensu/transport/rabbitmq.rb というファイルの存在。中身をちょっと覗いてみると…
gem "amqp", "1.3.0"
require "amqp"
require File.join(File.dirname(__FILE__), "base")
module Sensu
module Transport
class RabbitMQ < Base
def initialize
super
@queues = {}
end
def connect(options={})
timeout = create_connection_timeout
on_failure = on_connection_failure
@connection = AMQP.connect(options, {
:on_tcp_connection_failure => on_failure,
:on_possible_authentication_failure => on_failure
})
上記のように Gem の amqp を require していて RabbitMQ の為の設定を最小限に書くことができている…ということは類似のキュー処理が出来るミドルウェアで置き換えるのでは?という疑問と期待にぶつかります…。
さらに sensu-transport/lib/sensu/transport.rb を見ると…
module Sensu
module Transport
def self.connect(transport, options={})
require("sensu/transport/#{transport}")
klass = Base.descendants.detect do |klass|
klass.name.downcase.split("::").last == transport
end
object = klass.connect(options)
object
end
end
end
という記述があり、self.connect メソッドが受け取った引数が sensu/transport/ ディレクトリ以下のファイル名となるようなことから、前述のような RabbitMQ 意外の選択肢を選べる、または追加出来るような作りになっていることを垣間見れるますな。
ちなみに
sensu における RabbitMQ の使われ方
これは RabbitMQ の vhost と Exchange を確認した。
ソースコード的にはこのファイルに定義されている。整理すると以下のような感じになると思われる。
Exchange Name | Exchange Type | 用途 |
---|---|---|
keepalives | direct | Sensu クライアントとの死活監視 |
result | direct | Sensu クライアントのチェック結果をやりとりする |
test | fanout | Sensu クライアントに各種チェックを実行させる |
以下、該当部分を抜粋。
@transport.subscribe(:direct, 'keepalives', 'keepalives', :ack => true) do |message_info, message|
@transport.subscribe(:direct, 'results', 'results', :ack => true) do |message_info, message|
@transport.publish(:direct, 'results', MultiJson.dump(payload)) do |info|
@transport.publish(:fanout, subscription, MultiJson.dump(payload)) do |info|
RabbitMQ を想像させるような記述は :direct と :fanout くらいで amqp とかで検索すると見つからないから泣きたくなります。sensu-transport というライブラリを require して transport というインスタンス変数を呼ぶようになっていました。
ちょっと脱線…RabbitMQ の Exchange って何?
一言で言いますと…
- Exchange は生成された Message を受け取り Binding に従って、適切な Message Queue へ渡す
メッセージルーターようなイメージでしょうか。
ちょっと脱線…RabbitMQ の Exchange Type について
- Direct – Message の Routing key と Binding の Binding key をチェックして Routing key と Binding key が同じになるキューにメッセージを配送する
- Fanout – キューすべてに受け取ったメッセージの配送を行う
- Topic – Routing key を元に配送するキューを選択するがキーを階層で区切って部分一致でキューを選択してメッセージを配送する
RabbitMQ の Exchange についてはこちらの記事が解りやすい。上記のメモも本記事を参考にさせて頂いて自分なりに噛み砕いて書いた。
最後に
- つたない英語翻訳コンニャクで意訳、予想した内容なので、おおいに間違いがあると思います
- 実際にはソースコードを見るなり試すなりしてください
- RabbitMQ が嫌いなわけではないですが周辺ツールを自由に組み合わせて監視環境を構築する Sensu らしいなあって思ったりしています
元記事は、こちら