Author Archives: T.O.

About T.O.

Hadoop おじさん業を営んでいるが、元々は Java と Perl のウェブアプリケーションエンジニア。 実はまだウェブアプリケーションエンジニアとしてのキャリアの方がギリギリ長い。冬は毎週末スキーに行くため、夏はおとなしく過ごす。

2017-08-30

Apache Storm を使ってストリーム処理を書いてみよう

こんにちは。 Hadoop 周辺をよく触っている T.O. です。
Hadoop 周辺をよく触っているので、最近 Hadoop 周辺を触ってきて得た話などを書いていきます。

ということで今回は、数あるストリーム処理エンジンの中のひとつ Apache Storm を少々触ってストリーム処理を書いてみよう、という話を。

Apache Storm とは

ひとことで言えば、いわゆるストリーム処理エンジン。
以前、別のブログで Apache Apex について書きましたが、おおまかにはそれと同じカテゴリーに属するツールです。
例のごとく、詳しいことは 公式ドキュメントを熟読すればだいたいわかります(リンク先は 1.1.0 のもの)。
書籍は Amazon を調べれば多少見つかりますが、良書かどうかは不明です。このあたりの分野についてはウェブで英語で書かれたドキュメントを読むのが一番良いように思います。
日本語の資料だと、少し古いですが、 NTT データの方による「ストリームデータ分散処理基盤Storm」が概要をつかむにはよいかもしれません。

用語

ところで、以降の話を読み進めていただく上で、ある程度、用語への理解が必要になるので、その説明をごくかんたんにしておきます。
なお、今回は、 Storm を構成するプロセスについての説明は含みません(ので、 Nimbus などの話もしません)。

Topology

Topology (トポロジー)は、 Storm によるストリーム処理の流れ・構成を表したもので、 Spout (スパウト)と Bolt (ボルト)をつなげたものです。

Spout

Spout (スパウト)は、 Topology におけるデータの生成元になるノードです。データの生成、というのは、 Spout のコード中で生成することだけでなく、外部のデータソースから取り出すことも含みます。

Bolt

Bolt (ボルト)は、 Spout あるいは Bolt からデータを受け取り、なんらか処理をするものです。

Tuple

Tuple (タプル)は、 Storm の Topology において処理されるデータの単位です。一般的な Tuple と意味合いとしては同じです。 Storm におけるストリームというのは連続して流れてくる Tuple にほかなりません。

実装に使える言語

Storm の Topology, Spout そして Bolt の実装は基本的には Java でやることになります。もちろん Scala でも書けますし、さらには、 Clojure で書くこともできます
そしてさらに、非 JVM 言語でも書けます

Apache Storm を使ってストリーム処理をやってみよう

環境

今回も例のごとくGMOアプリクラウドを利用して環境を構築しています。
Storm については、 HDP 2.6.1 に含まれているもの( 1.1.0 ベース)を利用します。
本来、ストリーム処理などのいわゆる “Data in motion” 領域では同じ Hortonworks のディストリビューションを使うのであれば HDF(Hortonworks DataFlow) を使うのが筋といえば筋なのですが、たまたま勉強用に HDP 2.6.1 を使ったクラスタを用意してあり、 HDP 2.6.1 は Storm を含んでいるので、それを利用することにしました。
なお HDF については、以前、別のブログで NiFi を利用した処理の実装についてで書いていますので興味がある方は参考までに。

内容

今回は、実装したのは、端的に言えば Twitter でバースト検出です。 Twitter 公式で「トレンド」として提供されているアレです。
バースト検出というと他の例では、 Yahoo!JAPAN のサービスで言うところの「急上昇ワード」もそれにあたるだろうと思います。
しかし、まじめに実装するとそれなりに大変になるところだろう、ということと、今回はあくまで主眼は Storm でストリーム処理をしてみよう!というところなので、バースト検出そのものについては極めて雑にかんたんにやっています。
あくまで「何らかの条件にパスした語を取り出すフィルタ」ぐらいに思っていただいていて OK です。

さて、そんな Twitter バースト検出ですが、やることを一段階具体化すると、以下のようになります。

  1. Twitter のツイートを取り出し
  2. ツイートを形態素解析にかけて語に分割し
  3. 語の出現頻度等を見て、いわゆるバースト検出を行なう

では、それぞれのステップを具体的にしていきます。

まず最初の「Twitter のツイートを取り出し」です。
ツイートを取り出すことそのものは、 Twitter Streaming APIs の public stream を使えばできます。
今回は Java を使って実装することにしましたが、 Java で Twitter の API をたたくとなれば Twitter4J を使えばかんたんにできます。
そして、 Storm の Topology としては、これが Spout になります。

次に「ツイートを形態素解析にかけて語に分割し」ですが、今回は日本語のツイートを対象としたいので、いわゆる日本語形態素解析エンジンを使います。
日本語形態素解析エンジンはいろいろありますが、今回は kuromoji を使います。
kuromoji がサポートしている辞書にはいくつかありますが、 Twitter というサービスの性質上、新語にも対応していてくれた方がよいので、 kuromoji-ipadic-neologd を利用します。
こうして、ツイートを構成している語を出力するような Bolt を実装することができます。

Spout にしても Bolt にしても、それらを実装するにあたっては、指定のインターフェイスを実装したクラスを書くことになります。
それぞれ、おおもとをたどると ISpout インターフェイス、 IBolt インターフェイスですが、それを実装している BaseRichSpout クラスや BaseRichBolt クラスを extends してつくる方がお手軽といえばお手軽になるようです。

最後に「語の出現頻度等を見て、いわゆるバースト検出を行なう」を行います。
これも Bolt として実装します。
バースト検出のアルゴリズムは、本来であれば、 Bursty and Hierarchical Structure in Streams を実装するのが良いのですが、今回はそれ自体のアルゴリズムはほぼどうでもいい、としているので、「ある語が、一定時間の中で今までの平均よりも X 倍多く出現したらバーストしたとみなす」というシンプルなロジックにしています。
この「一定時間の中で」というのを実現するのはいわゆるウィンドウです。
Storm では、 Sliding Window と Tumbling Window に対応しています。
今回は Tumbling Window を使ったのですが、これは実現したい処理次第でしょう。
詳細は公式ドキュメントの解説をご覧ください。

さて、このようにして Spout と Bolt を用意するわけですが、さらにこれらを利用した Topology をつくる必要があります。
Topology をつくる、というのは、つまり Spout と Bolt を接続する、ということですが、例えば下記のコードのように書きます。

このようなコードを適当にクラスの main に実装します。 Topology については、 implements しないといけないインターフェイスはないようです。

このようにして実装した Topology, Spout, Bolt と依存しているライブラリをまとめた jar をつくり(この際には Apache Maven Assembly Plugin が役に立つでしょう)、下記のように storm コマンドを実行すれば、 Topology の開始、となります。

ところで、コードこそ出しませんが、今回、実装するにあたっては、最終的な結果、つまり「バーストした」として検出した語を HDFS に書き出していました。これは Storm にビルトインの HdfsBolt クラスを使えばかんたんに実現できます。が、特にバースト検出のようなアプリケーションの場合、 HDFS 上のファイルとして書き出す、というのは、利用する側から考えるとあまり適切とは言えないでしょう。こういうケースでは、例えば WebUI からのアクセスするものとして MySQL など RDB や HBase に書き出すような Bolt を用意するとよいかもしれません。

実行状況のモニタリング

ここまでで Topology を実装し、動かすことができたわけですが、実行の状況は専用の WebUI から確認することができます。これにより今まで処理したデータの量や、個々の Spout や Bolt でエラーが発生している場合はそのエラーメッセージを確認することができます。

まとめ

今回は Apache Storm を使ってかんたんなストリーム処理を実装してみました。
デモをお見せしないと実感しづらい話ではありますが、割りとあっけなく実装でき、動いてしまうので、みなさんもお試しください。

ちなみに、以前に試した Apache Apex と比べてみると、正直なところ、ビルトインの処理( Storm で言うところの Spout と Bolt, Apex で言うところの Operator )の充実度や、独自に書く場合の書きやすさ、運用のしやすさ( Apex は on YARN だが、 Storm の Nimbus や Supervisor など独自のコンポーネントがある)を考えると Apex の方がかんたんだったな、という感想になっています。利用実績としては恐らく Storm の方が上で、世界的にはノウハウも溜まっているとは思いますが…。

2016-10-14

今更だけど、 Nagios について知っておきたい 5 つのこと

みなさんは監視していますか? 健全な運用には、まずは適切な監視が重要です。そんな監視をするツールは、 2016 年現在いろいろありますが、そうは言っても、監視と言えばとりあえず Nagios です。ということで、今回はそんな Nagios について知っておきたいポイントを 5 つほど紹介したいと思います。

その 1: “Nagios” の読み方を知る

そもそも Nagios はどのように読む・発音するのでしょうか? 巷ではどうも「ナギオス」派と「ナジオス」派がいるようです。どちらが正しいのでしょうか。実はこの問いに対しては公式に答えが示されています。

Nagios Support – How do you pronounce Nagios?

つまりカタカナで書くならば「ナギオス」が公式見解に近いと言えましょう。

なお、以前は、公式サイトで Nagios の発音の mp3 が置いてあったのですが、 What is the correct pronunciation of Nagios? に “Answer originally linked to an mp3 audio file which contained the pronunciation as spoken by Ethan, the author of Nagios. File is no longer hosted by Nagios.” とありました。残念ですね…。

その 2: 必読の書籍を知る

まずは書籍です。幸いなことに Nagios については良い日本語で書かれた書籍があります。
“Nagios統合監視[実践]リファレンス”です。 Nagios に触るならば、手元に置いておきましょう。

その 3: Nagios による監視プログラム実行の 3 パターンを知る

Nagios による監視プログラム実行のパターンは 3 つあります。

  1. Nagios が監視プログラムを直接実行する
  2. Nagios がリモートの監視プログラムを NRPE で実行する
  3. 監視プログラムが NSCA を使って、結果を Nagios に通知する

1 は最もポピュラーなやり方です。デフォルトの監視項目はこれで動いています。これが大量にあると、 Nagios が動いているサーバで大量の監視プログラムのプロセスが起動することになります。

2 の NRPE = Nagios Remote Plugin Executer は 1 ではできない・やりづらいケースで用います。現実的にこれが有効なのは、「そのサーバにしか置いていないプログラムや設定ファイルを使うような監視」をやる場合でしょうか。ただし、 NRPE は、監視に用いたいコマンドを nrpe.cfg という設定ファイルに記述し、 Nagios の設定ファイル側では、その設定でのコマンド名を指定する、というようになります。例えば、 nrpe.cfg が以下のように記述されている場合、

これを呼び出すには Nagios 本体側の設定ファイルで以下のように記述することになります。

3 の NSCA = Nagios Service Check Acceptor はいわば監視プログラム側からのプッシュ型です。監視のタイミングを Nagios で定められるような定期的な設定にしたくない場合は、これの出番となります。例えば「ログに特定の文字列が書き出されたらその時点でアラートを上げる」という場合は、これを使うと自然にできます。

その 4: Nagios プラグインの書き方を知る

さて、どのような監視方式を選ぶにしても、任意の監視をやりたいとなると、 Nagios プラグインを自身で実装することになります。
Nagios プラグイン、とだけ聞くと、何か書くにあたってめんどくさいルールを覚えないといけないのでは、と臆してしまうこともあるかもしれませんが、基本的には 2 つのルールだけ覚えておけば OK です。

ルール 1: プログラムの exit status を Nagios プラグイン的にする

Nagios による監視のステータスというのは 4 種類あって、 OK, WARNING, CRITICAL, UNKNOWN ですが、これは Nagios プラグインの exit status にてそれぞれ 0, 1, 2, 3 に対応しています。つまり、

ステータスのラベル exit status の値
OK 0
WARNING 1
CRITICAL 2
UNKNOWN 3

 

ということです。自分で Nagios プラグインを書くときも、ただこれに従うだけで良いのです。

ルール 2: メッセージを標準出力に書き出せ。ただしもっとも重要なことは 1 行目に。

Nagios の WebUI の Services のような、監視項目(これを Nagios 的には service と呼んでいる)の一覧表では Status Information というところに、メッセージが表示されていますが、これは、 Nagios プラグインが標準出力に書き出した 1 行目( = 最初の改行文字よりも前の内容)です。そして、その監視項目の詳細を開くと 2 行目以降も表示されています。ということで、監視結果のステータスと合わせて伝えたい内容は、まず 1 行目に重要なことを書き、 2 行目以降により詳細な内容を書き出すようにしましょう。

また、その 1 行目・ 2 行目以降の内容は、 Nagios の内部的にはそれぞれ $SERVICEOUTPUT$, $LONGSERVICEOUTPUT$という変数で保持されています。このことを知っていると、監視の通知をするメールの本文の組み立てに活かすことができます。

その 5: 「通知」のためのプログラムを知る

Nagios というと「監視がひっかかったら、メールで通知してくれる」というイメージが強かろうと思いますが、この「メールで通知する」というのは、そもそもデフォルトではどう実現しているのでしょうか?

「通知」について知るには、まず contact の定義を読む必要があります。
contact は文字通り「連絡先」で、つまり、「通知」を出す相手を表すモノです。

この contact の定義に service_notification_commandshost_notification_commands という項目がありますが、これはそれぞれ service の監視・ host の監視で通知対象となったとき(WARNING や CRITICAL になったときや、そこから復帰して OK になったときなど)に呼び出すコマンドです。 commands と複数形で書かれているとおり、複数指定することができます

デフォルトで用意されている contact では、それぞれのコマンドとして notify-service-by-email や notify-host-by-email というのが指定されていますが、これらはそれぞれ、その名前で command として定義されています。そこで、 notify-service-by-email という command 定義を探してみると、デフォルトでは commands.cfg に定義されており、その command_line はデフォルトでは以下のようになっています。

これを読むとわかるとおり、実は単に、本文として送りたい内容を Nagios が用意している変数を使いつつ printf コマンドで書き出し、それを mail コマンドに食わせているだけなのです。

ここまで読み解いてくると、「通知」のためのプログラムというのも、なんら特別なことはない、ということがわかります。 “$” で囲まれている定義済みの変数を上手く使って、件名や本文を組み立てたコマンドを用意すれば OK です。この “$” で囲まれている変数の一覧は Standard Macros in Nagios で確認することができます。前のセクションで触れた $SERVICEOUTPUT$, $LONGSERVICEOUTPUT$ についても、こちらで紹介されています。

例えば Nagios と Slack を使っている人の場合は、これを使っているかもしれませんが、これも結局、定義済みの変数を上手く使って Slack の API を叩くようなプログラムを呼び出しているだけ、です。

まとめ

今回は、 Nagios を扱う際に知っておきたい 5 つのことを書いてみました。 Nagios とうまく付き合っていくために覚えておきましょう。