Kotlin
Embulk

embulk の plugin を kotlin で実装する

はじめに

こんにちは。データエンジニアリンググループでエンジニアをやっている@bandwagondagonです。
CETというプロジェクトで、分析をしたり機械学習活用のためのデータ基盤を開発したりしています。

業務の中で embulk を使ってETL()開発することがあり、その際にembulk-input-bigquery という plugin にPRを出すことが何度かありました。

そこで

という問題や想いが生まれたので、個人的に embulk-input-bigquery を kotlin で書き直してみることにしました。
本記事ではそこで得た知見として

を紹介しようと思います!

embulk とは?

embulk とは plugin 機構による柔軟なETL処理を実現している OSS の並列バルクデータローダーです。

plugin は

  • input-plugin (入力のデータソース)
  • filter-plugin (データ加工)
  • output-plugin (データの出力先)

の3種類に分けられ、 jruby と java の好きな言語で書くことができます。

(もっと embulk について詳しく知りたいという方には@hiroysatoさんのFluentdのバッチ版Embulk(エンバルク)のまとめが、2015年のリリース当時の情報から直近の勉強会での発表情報まで非常に詳しく関連情報をまとめられているのでオススメです。)

embulk の plugin で kotlin で書くための方法

事前に必要なこと

STEP1 : java で plugin を書くための設定

embulk mkbundle コマンドで生成される plugin のひな形は ruby で記述されているため、まず java で plugin を開発できる準備をします。

java で ビルドツールとして gradle を用いるのが一般的でしょうか。

embulk-input-jdbcbuild.gradle などを参考にタスク定義を書くのも良さそうですが、ここでは

@kamatama41 さんの gradle-embulk-plugin を使用したいと思います。

gradle-embulk-plugin

などといったbuild.gradle の設定をラップしてくれているため、以下のようにbuild.gradle の設定を非常に簡潔にすることができます。

buildscript {
    repositories {
        mavenCentral()
        maven { url 'http://kamatama41.github.com/maven-repository/repository' }
    }
    dependencies {
        classpath "com.github.kamatama41:gradle-embulk-plugin:0.1.4"
    }
}

apply plugin: "com.github.kamatama41.embulk"
repositories {
    mavenCentral()
    maven { url 'http://kamatama41.github.com/maven-repository/repository' }
}

embulk {
    version = "0.8.39"
    category = "input"
    name = "embulk-input-bigquery-kotlin"
    authors = ["Yuji Koyano"]
    email = "yuji.koyano.800@gmail.com"
    description = "embulk input plugin from bigquery written by kotlin."
    licenses = ["MIT"]
    homepage = "https://github.com/ykoyano/embulk-input-bigquery-kotlin"
}

また, gradle-embulk-plugin では java での plugin テンプレートを生成する newPluginというタスクをサポートしているため、これですぐに java で plugin の開発を始めることができます。

STEP2 : kotlin で plugin を書くための設定

前述の gradle-embulk-plugin を使用すれば kotlin の導入も非常に簡単に行うがことができます。

buildscript {
    ext.kotlinVersion = '1.2.10' # 記事執筆時点で最新
    repositories {
        mavenCentral()
        jcenter()
        maven { url 'http://kamatama41.github.com/maven-repository/repository' }
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
        classpath "com.github.kamatama41:gradle-embulk-plugin:0.1.4" # 記事執筆時点で最新
        classpath "net.researchgate:gradle-release:2.6.0" # 記事執筆時点で最新
    }
}

これだけで kotlin での embulk plugin の開発準備は完了しました。

参考記事

embulk-input-bigquery-kotlin

上記の build.gradle 設定を利用して、input ソースとして bigquery を扱う kotlin 実装の pluginembulk-input-bigquery-kotlin を作りました。

embulk-input-bigquery と比較してまだまだBQに関して設定できる項目や少なかったり、resumecleanup タスクや一部のデータ型に対応していないなど未完成な部分はありますが、今後対応していく予定です。

jruby 実装と kotlin実装 の比較

Bigquery の public data を用いて embulk-input-bigquery と embulk-input-bigquery-kotlin の読み込みのパフォーマンスを比較してみました。

速度比較に使った task 設定の yaml は以下の通りです。

embulk-input-bigquery-kotlin
in:
  type: bigquery
  project: <PROJECT_NAME>
  columns:
    - {name: id, type: long}
    - {name: author, type: string}
    - {name: time, type: long}
    - {name: text, type: string}
    - {name: parent, type: long}
  asynchronous_method: true
  cache: false
  standard_sql: true
  sql: "SELECT id, author, time, text, parent FROM `bigquery-public-data.hacker_news.comments` LIMIT 10000"

out:
  type: stdout
embulk-input-bigquery-kotlin
in:
  type: bigquery-kotlin
  columns:
    - {name: id, type: INT64}
    - {name: author, type: STRING}
    - {name: time, type: INT64}
    - {name: text, type: STRING}
    - {name: parent, type: INT64}
  sql: "SELECT id, author, time, text, parent FROM `bigquery-public-data.hacker_news.comments` LIMIT 10000"

out:
  type: stdout

timeコマンドで計測した処理時間(秒)の結果

embulk-input-bigquery embulk-input-bigquery-kotlin
real[s] 22.79 11.49
user[s] 47.01 17.90
sys[s] 1.39 0.80

実装を jruby から kotlin に変更するだけで、2倍近く処理時間に差が出ることが確認できました。

終わり

以上
- embulk の plugin を kotlin で書くための方法
- 実際に kotlin で実装した plugin embulk-input-bigquery-kotlin
の紹介でした。

embulk は jruby と java といった異なる言語での plugin 実装をサポートしているため、言語選択といった意味では、コントリビュートへの敷居 が低い OSS であると考えています。
また本記事で紹介したように kotlin での plugin 開発という選択肢も非常に面白いと思いますので、これ機会にぜひ皆さんも embulk の plugin 開発に参加してみて下さい!
また、もっとこう書いたらよいよ、などといったお話をコメントにてお待ちしております〜!