リアルタイム処理エンジン Gearpumpの紹介

560 views

Published on

#ScalaMatsuri のランチLT用リアルタイム処理エンジンGearpumpの紹介スライドです。
PC障害で使わずに紹介してましたが供養のためアップしておきます。

Published in: Engineering
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
560
On SlideShare
0
From Embeds
0
Number of Embeds
103
Actions
Shares
0
Downloads
2
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

リアルタイム処理エンジン Gearpumpの紹介

  1. 1. リアルタイム処理エンジン Gearpumpの紹介 2016/01/30 Kimura Sotaro(@kimutansk)
  2. 2. アジェンダ 1. Gearpumpとは? 2. 何故Gearpumpが必要なのか? 3. Gearpumpの特長 4. Gearpumpの構成 5. どうリアルタイム処理が組めるか? 1
  3. 3. 1. Gearpumpとは? • リアルタイムなデータ処理エンジン • Scala製のApache License OSS • Intelによって開発され、2014/7/23にOSS化 2 シンプルで強力な メッセージレベルの ストリーム処理Daemon •Communication •Concurrency •Isolation •Fault-tolerant akkaベースで構築され、シンプル、高性能
  4. 4. 1. Gearpumpとは? • ビッグデータスタック上の位置づけ 3 DataStore Execute Engine storm Here! DSL /Query Analytics
  5. 5. 2. 何故Gearpumpが必要なのか? • リアルタイムストリーム処理に求めたい性質 ① Keep the data moving ② Query using StreamSQL ③ Handle stream imperfections ④ Generate predictable outcomes ⑤ Integrate stored and streaming data ⑥ Guarantee data safety and availabilit ⑦ Partition and scale applications automatically ⑧ Process and Respond Instantaneously • 『Meet The 8 Requirements of Real-Time Stream Processing (2006)』 • 上記の性質を満たすストリーム処理基盤が必要 • Apache Flinkも同様の性質をもつ だが、小規模のCheckpointに区切る方式 4
  6. 6. 3. Gearpumpの特長 • 下記のような特長を持つ。 ① 高スループット ② 低レイテンシ ③ メッセージの処理信頼性設定可能 (At least once / exactly once)※但し条件あり ④ 高拡張性 ⑤ 動的DAG 5
  7. 7. 4. Gearpumpの構成 • コンポーネントは全てakka Actorで構成 • アドレス解決をAkkaを用いることで 全体のアーキテクチャはシンプルに出来ている。 6
  8. 8. 4. Gearpumpの構成 • 耐障害性もakka clusterで維持 • 親Actorは子Actorの状態を確認し、自動復旧 • 一番Rootとなる親はakka cluster / CRDTで冗長化 7 WorkerWorkerWorker Master standb y Master Standb y Master State Gossi p CRDT Data type example: leader
  9. 9. 5. どうリアルタイム処理が組めるか? • Gearpumpのアプリケーションは下記で構成 • 各ProcessorのActorコード • ActorをDAGとして組み合わせてアプリケーションとして デプロイするコード 8 例:WordCountを行うアプリケーション Split Sum 単語ごとに集約 Sum.scala Split.scala HashPartitioner (既存コンポーネント) WordCount.scala
  10. 10. 5. どうリアルタイム処理が組めるか? • Split.scala 9 class Split(taskContext : TaskContext, conf: UserConfig) extends Task(taskContext, conf) { import taskContext.{output, self} // 1. 自分自身にStartメッセージを通知。 override def onStart(startTime : StartTime) : Unit = { self ! Message("start") } // 2. 文章を単語に分割し、空文字を除去した上で下流に送信 override def onNext(msg : Message) : Unit = { Split.TEXT_TO_SPLIT.lines.foreach { line => line.split("[¥¥s]+").filter(_.nonEmpty).foreach { msg => output(new Message(msg, System.currentTimeMillis())) } } // 3. 次メッセージを自分に対して送信するタスクを仕掛ける import scala.concurrent.duration._ taskContext.scheduleOnce(Duration(100, TimeUnit.MILLISECONDS))(self ! Message("continue", System.currentTimeMillis())) } }
  11. 11. 5. どうリアルタイム処理が組めるか? • Sum.scala 10 class Sum (taskContext : TaskContext, conf: UserConfig) extends Task(taskContext, conf) { private[wordcount] val map : mutable.HashMap[String, Long] = new mutable.HashMap[String, Long]() private[wordcount] var wordCount : Long = 0 private var snapShotTime : Long = System.currentTimeMillis() private var snapShotWordCount : Long = 0 private var scheduler : Cancellable = null override def onStart(startTime : StartTime) : Unit = { // 1. 起動時に状態出力タスクを仕掛ける。 scheduler = taskContext.schedule(new FiniteDuration(5, TimeUnit.SECONDS), new FiniteDuration(30, TimeUnit.SECONDS))(reportWordCount) } override def onNext(msg : Message) : Unit = { if (null == msg) { return } // 2. 受信したメッセージから単語を取得し、総受信回数と単語ごとの受信回数をカウント val current = map.getOrElse(msg.msg.asInstanceOf[String], 0L) wordCount += 1 map.put(msg.msg.asInstanceOf[String], current + 1) }
  12. 12. 5. どうリアルタイム処理が組めるか? • WordCount.scala 11 object WordCount extends AkkaApp with ArgumentsParser { private val LOG: Logger = LogUtil.getLogger(getClass) val RUN_FOR_EVER = -1 // 1. 起動時のCLIから読み込む項目と形式、注釈、必須/オプショナル、デフォルト値を定義 override val options: Array[(String, CLIOption[Any])] = Array( "split" -> CLIOption[Int]("<how many split tasks>", required = false, defaultValue = Some(1)), "sum" -> CLIOption[Int]("<how many sum tasks>", required = false, defaultValue = Some(1)) ) def application(config: ParseResult) : StreamApplication = { // 2. CLIから読み込んだ設定項目を用いてProcessorを生成 val splitNum = config.getInt("split") val sumNum = config.getInt("sum") val split = Processor[Split](splitNum) val sum = Processor[Sum](sumNum) // 3. メッセージのProcessor間の割り振りを行うPartitionerを生成 val partitioner = new HashPartitioner // 4. ProcessorとPartitionerを用いてDAGを作成 val app = StreamApplication("wordCount", Graph(split ~ partitioner ~> sum), UserConfig.empty) app } 非常に直観的にグラフが 組める!
  13. 13. Enjoy Gearpump!

×