🔄

Kafkaのプロトコルスタックがわからなかったので試してみた

に公開

はじめに

ガチガチに固められたネットワークにKafkaを通そうと思ったのだけれど、プロトコルスタックやパケットフォーマットがわかんないな、と思って試してみました。

アーキテクチャの説明や性能評価の記事は結構あるのですけど、プロトコルスタックやパケットフォーマットはいまいち見つけられなかったので試してみることにします。

https://aws.amazon.com/jp/what-is/apache-kafka/

Kafka は TCP 経由のバイナリプロトコルを使用します。

その「バイナリプロトコル」の中身を知りたいかなって。

とりあえずローカルにデプロイ

Quickstartがあったので、これに沿ってデプロイしていく。
4.0でZooKeeperが廃止されてKRaftに移行してしまったようですが、とりあえずZooKeeperで試すべく3.9でやってみます。

https://kafka.apache.org/quickstart

% tar -xzf kafka_2.13-3.9.0.tgz
% cd kafka_2.13-3.9.0.tgz
% bin/zookeeper-server-start.sh config/zookeeper.properties

でZookeeperを立ち上げつつ、別ターミナルでKafka Server立ち上げ。

% bin/kafka-server-start.sh config/server.properties

各種操作に対するパケットフォーマット

トピック作成

さらに別ターミナルでProducerを立ち上げ
適当なトピック名 quickstart-events を指定してトピックを作成。

% bin/kafka-topics.sh --create --topic quickstart-events --bootstrap-server localhost:9092

作成トピックを確認。ちゃんとできてそう。

% bin/kafka-topics.sh --describe --topic quickstart-events --bootstrap-server localhost:9092
Topic: quickstart-events	TopicId: wnMnz_FKTfGemhluhiFXJg	PartitionCount: 1	ReplicationFactor: 1	Configs: 
	Topic: quickstart-events	Partition: 0	Leader: 0	Replicas: 0	Isr: 0	Elr: N/A	LastKnownElr: N/A

TCPパケットはどうなっているかというと…

CreateTopics Request/Responseがやりとりされて、サーバ側でトピックが作成されることがわかりました。
(追加でメタデータもやりとりされる)

Producerからのメッセージ送信

Producerからメッセージを送り込んでみる。
対話プロンプトが出てくるので適当にメッセージを入れる。

% bin/kafka-console-producer.sh --topic quickstart-events --bootstrap-server localhost:9092
>Test event message no one.
>Test event message no two.
>Test event message no three.

TCPパケット。

TopicごとのMessageがセットされたRequest/Responseが、メッセージごとに発生。
3回入力したので3往復6メッセージ発生していることが見えました。

Consumerでのメッセージ受信

新たなターミナルを立ち上げて、Consumerとして動作させてみる。
Consumerを立ち上げた時点で、今まで入れた3つのメッセージが表示される。

% bin/kafka-console-consumer.sh --topic quickstart-events --from-beginning --bootstrap-server localhost:9092
Test event message no one.
Test event message no two.
Test event message no three.

TCPパケット。

Consumerを立ち上げたタイミングでfetchシーケンスが開始される。
Fetchシーケンスが秒ごとに実行され、その応答に「そのタイミングで未取得の」メッセージが入ってくる模様。
Fetchリクエストで「どこまで取得済みか」のOffset値が指定されているので、ServerはConsumerに対してOffset値より大きいメッセージを返しているように見える。

Consumer起動中にProducerからメッセージ送信

ConsumerでメッセージをFetchしている状態で、Producerからメッセージを送信してみる。

bin/kafka-console-producer.shのターミナル
>Test event message no four.


Producer側からのRequest/Responseで新しいメッセージが登録される。


Consumer側は直近のタイミングのFetch Responseで新しいメッセージの応答が返ってくる。


後続のConsumer側のFetch RequestではOffset値が4に更新される。
最新のメッセージが4なので、その後のResponseには何も入らない (=メッセージ更新はない判定)。

また今度やってみること

Fetch頻度は fetch.max.wait.ms のあたりで変えられそうなので、変えてみて試してみたい。

あとは4.0からはKRaftに移行しているはずなので、そちらも試してみたいですね。
ZooKeeperだとメタデータ管理がボトルネックになっているので、KRaftでメタデータ管理も分散させるような思想の模様。
大規模だとこちらの方が良いのでしょうね。

https://aws.amazon.com/jp/blogs/news/introducing-support-for-apache-kafka-on-raft-mode-kraft-with-amazon-msk-clusters/

おわりに

Kafkaのパケットフォーマットやプロトコルスタックがわからなかったので、ハンズオンして試してみました。
細かい動作はこれからですが、ざっくりは理解できたので良かったです。

Discussion