Slide 1

Slide 1 text

Apache Kafkaとストリーム処理 Tomoyoshi Ogura 2018/05/26 JJUG CCC 2018 Spring

Slide 2

Slide 2 text

© ChatWork ● 小椋友芳 ● ChatWork株式会社コアテクノロジー開発室所属 ○ ソフトウェアエンジニア ○ サーバーサイド開発 ● Java、Scala、Akka、Golang、DDD、Kafka ○ JavaはJDK 1.2から使ってます ○ Kafkaは2016年からプロダクトで利用 ● twitter: @tomoyoshi_ogura ● github: tarugo07 自己紹介 JJUG CCC 2018 Spring

Slide 3

Slide 3 text

© ChatWork ● 業務の効率化と会社の成長を目的とした ビジネスコミュニケーションツールを開発、運営 ● 導入企業社数: 17万4000社以上(2018年4月末日時点) ● ビジョン:世界の働き方を変える ● Scala、PHP、Swift、Kotlin等で開発 ● エンジニア募集中です ○ Scalaで開発したいJavaエンジニアの方 ○ https://corp.chatwork.com/ja/recruit/ 会社紹介 JJUG CCC 2018 Spring

Slide 4

Slide 4 text

© ChatWork ● Apache Kafkaとストリーム処理 ● Akka Streamsの基本とプログラムの書き方 ● Apache Kafkaの基本 ● Alpakka Kafka Connectorの使い方 ● まとめ アジェンダ JJUG CCC 2018 Spring

Slide 5

Slide 5 text

© ChatWork Apache Kafkaとストリーム処理 JJUG CCC 2018 Spring

Slide 6

Slide 6 text

© ChatWork Apache Kafkaとは ● 2011年にLinkedInが公開した分散メッセージングシステム ● 大量のデータを高速に収集してリアルタイムに処理する ● Pull型(Publish-Subscribeモデル)を採用しているのでスループットの調整ができる ● ダウンタイムなしにスケールすることができる ● クラスタ化により耐障害性や高可用性を実現している ● ディスクに永続化することで長時間データを保持できる ● メッセージの到達保証があるのでデータを失い難い JJUG CCC 2018 Spring

Slide 7

Slide 7 text

© ChatWork システム間でデータを連携するためのハブやデータの集約先として利用 Apache Kafkaのユースケース JJUG CCC 2018 Spring

Slide 8

Slide 8 text

© ChatWork ● 大量のデータをリアルタイムに処理するにはストリーム処理が重要 ● ストリーム処理の特徴 ○ 無限に発生するデータを処理する ○ 処理が永続的に継続する ○ リアルタイム(低レイテンシ)に処理を行う ● ストリーム処理の課題 ○ 受信側の処理能力の限界を超えたデータを送信してしまうことがある ストリーム処理 JJUG CCC 2018 Spring

Slide 9

Slide 9 text

© ChatWork ● ノンブロッキングなバックプレッシャーを持つ非同期ストリーム処理の標準仕様 ○ Reactive Streams ● Java 9で標準化されてインターフェースが追加 ○ JEP 266: More Concurrency Updates ○ java.util.concurrent.Flow ● 主な実装 ○ Akka Streams ○ Ratpack ○ Reactor ○ RxJava Reactive Streams JJUG CCC 2018 Spring

Slide 10

Slide 10 text

© ChatWork ● Alpakka Kafka Connector ○ Apache KafkaをAkka Streamsに接続するためのコネクタ ○ Akka Streamsのコネクタを提供するプロジェクトであるAlpakkaで提供 ○ Akka Streamsからの利用が前提になっているので実装が簡単にできる このセッションではJavaでのAkka Streamsを使ったプログラムの方法とAlpakka Kafka Connector をAkka Streamsで利用する方法を説明します。 KafkaでReactive Streams JJUG CCC 2018 Spring

Slide 11

Slide 11 text

© ChatWork Akka Streamsの基本 JJUG CCC 2018 Spring

Slide 12

Slide 12 text

© ChatWork ● Reactive Streamsの実装の1つ ○ バックプレッシャーによる制御フロー ○ ノンブロッキング ○ 非同期ストリーム処理 ● アクターベースで処理を実行 ● 豊富な定義済み処理ステージ ● 型安全 Akka Streamsとは JJUG CCC 2018 Spring

Slide 13

Slide 13 text

© ChatWork プロジェクトにakka-streamモジュールの依存関係を追加する ● Maven ● Gradle ● SBT Akka Streamsを使うには JJUG CCC 2018 Spring

Slide 14

Slide 14 text

© ChatWork Akka Streamsの用語としてグラフと処理ステージがある ● グラフとはストリームデータが流れる一連の処理経路の定義 ● 処理ステージとはグラフを構築する処理ブロック ○ Source、Sink、Flowの3種類に分類される Akka Streamsの用語 JJUG CCC 2018 Spring

Slide 15

Slide 15 text

© ChatWork Source ● 1つの出力を持つ処理ステージ ● 下流の処理ステージがデータを受け取る準備ができている時に出力する ● 定義済みの処理ステージにはfrom、single、repeat、rangeなどがある Source JJUG CCC 2018 Spring

Slide 16

Slide 16 text

© ChatWork Sink ● 1つの入力を持つ処理ステージ ● 上流の処理ステージにデータの受け入れを要求する ● 受け入れ速度によっては上流の処理ステージを遅らせる可能性がある ● 定義済みの処理ステージにはforeach、fold、seq、ignoreなどがある Sink JJUG CCC 2018 Spring

Slide 17

Slide 17 text

© ChatWork Flow ● 1つの入力と出力を持つ処理ステージ ● 上流と下流を接続し、データの変換を行う ● 定義済みの処理ステージにはmap、filter、drop、takeなどがある Flow JJUG CCC 2018 Spring

Slide 18

Slide 18 text

© ChatWork RunnableGraph ● 両端をそれぞれSourceとSinkに接続されている ● 実行準備ができているグラフ RunnableGraph JJUG CCC 2018 Spring

Slide 19

Slide 19 text

© ChatWork 処理ステージを合成すると新たな処理ステージになる ● SourceとFlowを繋げるとSourceになる ● FlowとSinkを繋げるとSinkになる ● FlowとFlowを繋げるとFlowになる 処理ステージの合成 JJUG CCC 2018 Spring

Slide 20

Slide 20 text

© ChatWork Akka Streamsを実行するには次の2つのステップが必要 1. 処理ステージを定義する ○ Sink、Source、Flowを定義する ○ Sink、Source、Flowを繋げてRunnableGraphを作成 2. 作成したグラフを実行 Akka Streamsを実行するには JJUG CCC 2018 Spring

Slide 21

Slide 21 text

© ChatWork 1から100までの数値で10の倍数の数値を標準出力に表示する 実際にAkka Streamsの実行してみる JJUG CCC 2018 Spring

Slide 22

Slide 22 text

© ChatWork Materialized values JJUG CCC 2018 Spring

Slide 23

Slide 23 text

© ChatWork 処理ステージが提供する補助値で実行(materialize)された時に得られる値 処理結果を取得したり、外部からストリームの制御を行う事ができる Materialized values JJUG CCC 2018 Spring

Slide 24

Slide 24 text

© ChatWork 処理ステージの合成時に提供するMaterialized valuesを指定する事が可能 合成時のMaterialized valuesの指定 JJUG CCC 2018 Spring

Slide 25

Slide 25 text

© ChatWork ファイルのバイト数と行数を確認する Materialized valuesを実行してみる JJUG CCC 2018 Spring

Slide 26

Slide 26 text

© ChatWork エラー処理 JJUG CCC 2018 Spring

Slide 27

Slide 27 text

© ChatWork ● デフォルトではストリーム処理中に例外が発生すると停止する ● スーパーバイザー戦略を指定することで動作を変更することができる ● 指定できる戦略 ○ Stop:失敗としてストリーム処理を停止する(デフォルト) ○ Resume:問題の要素を捨ててストリーム処理を続行する ○ Restart:問題の要素を捨てて処理ステージを再起動する(処理ステージの状態は破棄) ● スーパーバイザー戦略を指定する方法 ○ マテリアライザーに指定 ○ 処理ステージに指定 ○ スーパーバイザー戦略の判定順位は処理ステージが優先される エラー処理 JJUG CCC 2018 Spring

Slide 28

Slide 28 text

© ChatWork スーパーバイザー戦略をマテリアライザーに指定 スーパーバイザー戦略の指定 JJUG CCC 2018 Spring

Slide 29

Slide 29 text

© ChatWork スーパーバイザー戦略を処理ステージに指定 スーパーバイザー戦略の指定 JJUG CCC 2018 Spring

Slide 30

Slide 30 text

© ChatWork ストリームのテスト JJUG CCC 2018 Spring

Slide 31

Slide 31 text

© ChatWork ● Akka Streamsの処理ステージをテストする方法は色々ある ○ akka-testkitモジュールのTestProbeを利用 ○ akka-stream-testkitモジュールのテスト用のSourceやSinkを利用 ● どの方法でもSource、Sink、Flowといった処理ステージを別々に保持しておくことが重要 Akka Streamsのテスト JJUG CCC 2018 Spring

Slide 32

Slide 32 text

© ChatWork プロジェクトにakka-testkitモジュールの依存関係を追加する ● Maven ● Gradle ● SBT akka-testkitを使うには JJUG CCC 2018 Spring

Slide 33

Slide 33 text

© ChatWork プロジェクトにakka-stream-testkitモジュールの依存関係を追加する ● Maven ● Gradle ● SBT akka-stream-testkitを使うには JJUG CCC 2018 Spring

Slide 34

Slide 34 text

© ChatWork テストモジュールを使わないテスト方法 テストモジュールを使わないテスト JJUG CCC 2018 Spring

Slide 35

Slide 35 text

© ChatWork Akka StreamsがActorに変換されて実行されるのでTestPorbeを使ってテスト可能 TestProbeを使ったテスト JJUG CCC 2018 Spring

Slide 36

Slide 36 text

© ChatWork TestSourceはSourceの機能の実現できる TestSourceを使ったテスト JJUG CCC 2018 Spring

Slide 37

Slide 37 text

© ChatWork TestSinkはSinkの機能を実現できる TestSinkを使ったテスト JJUG CCC 2018 Spring

Slide 38

Slide 38 text

© ChatWork Apache Kafkaの基本 JJUG CCC 2018 Spring

Slide 39

Slide 39 text

© ChatWork ● KafkaはBroker(cluster)、Producer、Consumerで構成される ● Producerはメッセージの配信を行う ● Consumerはメッセージの購読を行う ● BrokerはProducer、Consumer間でメッセージの受け渡しを行うためのキュー Kafkaの基本構成 JJUG CCC 2018 Spring

Slide 40

Slide 40 text

© ChatWork ● KafkaはTopicにメッセージを保存する ● Topicは負荷分散のため1つ以上のPartitionに分割されている TopicとPartition JJUG CCC 2018 Spring

Slide 41

Slide 41 text

© ChatWork ● offsetはPartition内でメッセージを一意に識別する番号 ● ConsumerはPartitionのメッセージを何処まで読み取ったかoffsetで追跡する ● commitはPartitionの現在のoffsetを更新すること Consumerとoffset JJUG CCC 2018 Spring

Slide 42

Slide 42 text

© ChatWork ● Consumerはグループ単位でメッセージを購読する ● 1つのPartitionは1つのグループの1つのConsumerが購読する ● Consumerの並列数はPartitionの数以下になる Consumer Group JJUG CCC 2018 Spring

Slide 43

Slide 43 text

© ChatWork Alpakka Kafka Connector JJUG CCC 2018 Spring

Slide 44

Slide 44 text

© ChatWork ● Akka Streamの処理ステージとしてKafkaにアクセスするためのライブラリ ○ Producer、Concumerの両方を処理ステージに組み込める ● Akka Streamsのコネクタを提供するプロジェクトであるAlpakkaのコンポーネントの1つ ○ 以前はAkka Streams KafkaやReactive Kafkaとよばれていた Alpakka Kafka Connector JJUG CCC 2018 Spring

Slide 45

Slide 45 text

© ChatWork プロジェクトにakka-stream-kafkaモジュールの依存関係を追加する ● Maven ● Gradle ● SBT Alpakka Kafka Connectorを使うには JJUG CCC 2018 Spring

Slide 46

Slide 46 text

© ChatWork ● Producerの作成時にはProducerSettingsに設定情報を登録する ○ 接続先するKafka Broker ○ キーと値のSerializer ○ チューニングパラメータ ● 設定情報はapplication.confから設定することも可能 Producer JJUG CCC 2018 Spring

Slide 47

Slide 47 text

© ChatWork SinkにKafkaProducerを組み込む SinkでProducerを使う JJUG CCC 2018 Spring

Slide 48

Slide 48 text

© ChatWork FlowにKafkaProducerを組み込む FlowでProducerを使う JJUG CCC 2018 Spring

Slide 49

Slide 49 text

© ChatWork ● Consumerの作成時にはConsumerSettingsに設定情報を登録する ○ 接続するKafka Broker ○ Consumer Group ID ○ キーと値のDeserializer ○ チューニングパラメータ ● 設定情報はapplication.confから設定することも可能 Consumer JJUG CCC 2018 Spring

Slide 50

Slide 50 text

© ChatWork ConsumerでKafkaからメッセージ読み込む offsetのcommitはenable.auto.commitによる Consumerを使う JJUG CCC 2018 Spring

Slide 51

Slide 51 text

© ChatWork メッセージ保証とConsumerでの処理方法 ● At Most Once ○ 重複はないがロストする可能性がある ○ メッセージを受け取りoffsetをcommitしてから処理を実行 ● At Least Once ○ 必ず一回処理されるが重複する可能性がある ○ メッセージを受け取って処理を実行してからoffsetをcommit ● Exactly Once ○ 正確に一回処理され重複もロストもない ○ メッセージの処理とoffsetのcommitを同時に行う ○ offsetを外部ストレージに保存しないと難しい Consumerのメッセージ保証について JJUG CCC 2018 Spring

Slide 52

Slide 52 text

© ChatWork At Most Onceでの実行 At Most Once JJUG CCC 2018 Spring

Slide 53

Slide 53 text

© ChatWork At Least Onceでの実行例 1件ずつoffsetをcommitするので遅い At Least Once JJUG CCC 2018 Spring

Slide 54

Slide 54 text

© ChatWork At Least Onceでの実行例 offsetのcommitを複数件まとめて行うので速いが重複になる件数も増える At Least Once (Batch Commit) JJUG CCC 2018 Spring

Slide 55

Slide 55 text

© ChatWork ● 大量のデータをリアルタイムに処理するにはストリーム処理が大事です ● Reactive Streamsに準拠した実装ならマシンの性能を最大限に活かせる ● Akka Streamsは処理ステージを細かく分けて実装できるので見通しが良くなる ● Alpakka Kafka ConnectorでKafkaの処理をReactive Streamsとして扱うことができます まとめ JJUG CCC 2018 Spring

Slide 56

Slide 56 text

© ChatWork ご清聴ありがとうございました JJUG CCC 2018 Spring