CUBE SUGAR CONTAINER

技術系のこと書きます。

Mac OS X で Apache Kafka を触ってみる

Apache Kafka は OSS の分散型メッセージングミドルウェア。 似た性質を持ったソフトウェアとしては ActiveMQRabbitMQ などが挙げられる。 ただし、ActiveMQ や RabbitMQ との大きな違いは、独自のバイナリプロトコルを用いてメッセージをやり取りするところ。 ActiveMQ や RabbitMQ は標準化された AMQPMQTT を扱う場合が多い。 独自プロトコルというと、なんだか未来が無さそうなイメージがあるけど、その逆で Kafka はビッグデータ処理の場面ではほぼデファクトの位置にあるようだ。

今回は、そんな Kafka を手元の Mac でさくっと試してみることにする。 使った環境は次の通り。

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.4
BuildVersion:   16E195

インストールする

Kafka は Homebrew でインストールできる。 なので、まずは Homebrew をインストールしておく。 その上で Homebrew Cask についても使えるようにしておく。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew tap caskroom/cask

Kafka は Java と Scala を使って書かれている。 なので、まずは動作に必要な Java の処理系をインストールする。

$ brew cask install java

あとはお目当ての Kafka をインストールするだけ。

$ brew install kafka

このとき、依存パッケージとして Apache ZooKeeper もインストールされる。

サービスを動かす

続いてはインストールした Kafka を動作させる。 これには Homebrew のサービス機能を使うと楽ができる。

インストールした直後では Kafka と ZooKeeper は動いていない。

$ brew services list
Name      Status  User Plist
kafka     stopped
zookeeper stopped

そこで ZooKeeper と Kafka を順番に立ち上げていく。

$ brew services start zookeeper
$ brew services start kafka

両方のサービスが立ち上がればオッケー。

$ brew services list           
Name      Status  User    Plist
kafka     started amedama /Users/amedama/Library/LaunchAgents/homebrew.mxcl.kafka.plist
zookeeper started amedama /Users/amedama/Library/LaunchAgents/homebrew.mxcl.zookeeper.plist

ちなみに、上記の機能を使わなくても次のようにしてコマンドラインから起動することもできる。

$ zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties
$ kafka-server-start /usr/local/etc/kafka/server.properties

もし、上手く立ち上がらないときは、それぞれのログを確認しよう。 ログはデフォルトで /usr/local/var/log に保存されている。

同梱されているコマンドで Kafka を操作してみる

Kafka には操作するためのコマンドラインツールが同梱されている。 今回は、それを使ってみる。

トピックを作る

まずは、動作確認用のトピックを作成する。 トピックは Pub/Sub 型のメッセージングミドルウェアによく登場する概念だ。 これは、例えば扱うメッセージの種類やコンポーネントごとに用意する。

$ kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
Created topic "test".

--replication-factor オプションはクラスタ内でのメッセージのレプリケーション数を表している。 今回はシングルホスト構成なので必然的に 1 となる。 --partitions オプションはトピックでメッセージを分散処理するための機能の指定で、これを使った例については後ほど紹介する。

まずは、これで動作確認用の test トピックができた。

$ kafka-topics --list --zookeeper localhost:2181
test

メッセージを読み書きする

次に、作成したトピックに対してコンシューマ、つまりメッセージをトピックから読み出す存在を接続する。

$ kafka-console-consumer --bootstrap-server localhost:9092 --topic test --from-beginning

続いて、作成したトピックに対してプロデューサ、つまりメッセージをトピックに書き込む存在を接続する。 ターミナルから、何か適当にメッセージを書き込んでみよう。

$ kafka-console-producer --broker-list localhost:9092 --topic test
Hello, World!

すると、先ほど接続したコンシューマに、プロデューサが書き込んだメッセージが送られる。

$ kafka-console-consumer --bootstrap-server localhost:9092 --topic test --from-beginning
Hello, World!

ちなみに、Kafka のメッセージはデフォルトで永続化されている。 例えば、Ctrl-C で一旦コンシューマを停止させてから、もう一度立ち上げてみよう。

$ kafka-console-consumer --bootstrap-server localhost:9092 --topic test --from-beginning
Hello, World!

ちゃんと、先ほど受信したのと同じ内容が表示された。 これは、Kafka を再起動しても同じ結果になるので試してみると面白い。

ちなみに、コマンドを --from-beginning オプションを付けずに実行すれば、途中から受信できる。

$ kafka-console-consumer --bootstrap-server localhost:9092 --topic test

複数のコンシューマでメッセージを分散処理する

これまでの例では、トピックを作るときにパーティションを 1 に指定した動作を試してきた。 次は、複数のコンピューマでメッセージを分散処理するために、トピックに複数のパーティーションを作ってみる。

今度はトピック greet をパーティーション数 2 で作成する。

$ kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 2 --topic greet
Created topic "greet".

続いては、作成したトピックにコンシューマを接続する。 このとき、自身が受信するパーティションを --partition オプションで指定する。 一つ目のターミナルでは、まずは 0 を指定しておく。

$ kafka-console-consumer --bootstrap-server localhost:9092 --partition 0 --topic greet --from-beginning

続いて別のターミナルを開いて、パーティーションが 1 のコンシューマを接続する。

$ kafka-console-consumer --bootstrap-server localhost:9092 --partition 1 --topic greet --from-beginning

次はトピックにプロデューサを接続して、適当にメッセージを送ってみよう。

$ kafka-console-producer --broker-list localhost:9092 --topic greet
Message1
Message2

すると、送ったメッセージがバラバラにコンシューマに届くことが分かる。 まず、最初のメッセージはパーティーション 0 のコンシューマに送られた。

$ kafka-console-consumer --bootstrap-server localhost:9092 --partition 0 --topic greet --from-beginning
Message1

そして、二番目のメッセージはパーティーション 1 のコンシューマに送られている。

$ kafka-console-consumer --bootstrap-server localhost:9092 --partition 1 --topic greet --from-beginning
Message2

このように、パーティーションの機能を使うことでメッセージを複数のコンシューマで分散処理できるようになっている。

まとめ

今回は Mac OS X を使って Apache Kafka を軽く触ってみた。 実運用に載せるなら色々と考えるところはあるけど、手元の検証用としてなら簡単に環境を用意して触れることが分かった。 Apache Kafka はビッグデータ処理のメッセージングミドルウェアとしてはデファクトの存在なので引き続き知見を貯めていきたい。