Presto コネクターを実装する 第一回

こんにちは。松本です。

弊社ではマーケティングや CRM 関連の SaaS を開発/運営していますが、近年、この領域で利用するデータの規模がますます大きくなっています。またそれに伴い、データの格納先も従来のように「RDB のみ」というわけにはいかず用途によって様々に分かれてきています。

しかしこれらのデータをシステム上で統合して扱おうとすると、その方法に頭を悩ませます。Hadoop/HDFS ベースにデータを集め、Hive 等を使ってバッチ処理させるというアプローチも良いですが、お客様やプロダクト企画チームからの期待は「よりインタラクティブ」な処理です。

Facebook 社によって公開されたオープンソースの分散処理基盤である Presto はこういった課題に対するソリューションです。

そこで今回は Presto のインストール方法について記事を書こう・・・と思ったのですが、スズキ編集長から「それだけじゃ面白くないじゃん」的な理不尽な発言を頂いたので、Presto を更に活用することを可能にする Presto コネクターの実装方法について、何回かに分けて記事を書くことにしました。

Presto コネクターとは?

コネクターは Presto が各種データソースにアクセスすることを可能にするアダプター的なもので、本記事執筆時点で Java8 ベースで Service Provider が使われています。

JAR File Specification - Service Provider
http://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Service_Provider

既存のコネクター実装として、Cassandra、Hive、MySQL、PostgreSQL 等のコネクターが提供されています。

Presto Document - 4. Connectors
https://prestodb.io/docs/current/connector.html

Presto コネクター開発手順

実は現時点ではコネクター開発に関するドキュメントは少なく、オープンソースで公開されている実際のコネクターのソースを見ながら開発するしかありません。
# javadoc にも期待できません・・。

Presto Document - 9. Developer Guide
http://facebook.github.io/presto/docs/current/develop.html

Github facebook/presto
https://github.com/facebook/presto

Github にある presto-example-http というのがコネクターのサンプルとなっています。

presto-example-http
https://github.com/facebook/presto/tree/master/presto-example-http

本記事ではこの presto-example-http を使って解説してもよかったのですが、入門編としてわかりやすい記事になるよう、更にシンプルなオリジナルコネクターを作りながら解説することにしました。

開発手順はざっくりと次の通り。

  1. Presto Plugin インターフェースの取得
  2. コネクターの実装
  3. プロパティファイルの作成
  4. ファイルの配置
  5. Presto の設定変更
  6. Presto の再起動
  7. 動作確認

この順番で解説していきます(連載途中で変更するかもしれませんが)。

1. Presto Plugin インターフェースの取得

本記事を書いている時点で Presto 最新バージョンは 0.101 ですが、都合上今回は 0.96 を使います(私の開発環境が現在 0.96 なのです。0.101 に上げる時間が取れなかったというだけです。ごめんなさい)。

コネクター開発では presto-spi を使います。

その他、必要なものを含めた build.gradle は次のようになります。

ほとんどのライブラリは Presto 本体の lib ディレクトリに置かれているため、provided コンフィギュレーションで指定しています。

lombok は必須ではありませんが、本記事を書くにあたり趣旨と関係の薄い無駄なコードを省くことが出来るので利用することにしました(lombok についてはいずれ本ブログ内で誰かが紹介記事を書くと思います)。

lombok のインストール方法は下記を参考にして下さい。

Project Lombok - Download
http://projectlombok.org/download.html

CodeZine - Java特有の冗長なコードを簡潔に記述する「Lombok」
http://codezine.jp/article/detail/7274

2. Presto コネクターの実装

クラス構成

本記事では固定のテーブル/データを扱う ReadOnly なコネクターを開発します。

最小構成で実現する為、実装クラスは次の十数ファイル程度になります。

TechscorePrestoPlugin implements com.facebook.presto.spi.Plugin

Service Provider の実装クラスです。TechscoreConnectorFactory オブジェクトを生成する役割を担います。

TechscoreConnectorFactory implements com.facebook.presto.spi.ConnectorFactory

その名の通り、コネクターのファクトリクラスで、TechscoreConnector オブジェクトを生成します。コネクターオブジェクトの生成には com.google.inject.Injector を使い、必要な情報をインジェクションします。

TechscoreModule implements com.google.inject.Module

コネクタ生成時のインジェクションで使います。

TechscoreConnector implements com.facebook.presto.spi.Connector

コネクターオブジェクトです。コネクターとして必要な各種オブジェクトを返すだけのクラスです。

TechscoreMetadata extends com.facebook.presto.spi.ReadOnlyConnectorMetadata

スキーマやテーブルに関するメタデータを返すクラスです。

TechscoreHandleResolver implements com.facebook.presto.spi.ConnectorHandleResolver

各種ハンドルクラスを扱う為のリゾルバークラスです。ハンドルクラスには以下のようなテーブル情報を扱うものやカラム情報を扱うもの等があります。

TechscoreTableHandle implements com.facebook.presto.spi.ConnectorTableHandle

テーブル情報を扱う為のクラスです。 ConnectorTableHandle 自体は空のインターフェースですので、何を実装するかは開発者に委ねられています。

TechscoreColumnHandle implements com.facebook.presto.spi.ConnectorColumnHandle

カラム情報を扱う為のクラスです。 ConnectorColumnHandle 自体は空のインターフェースですので、何を実装するかは開発者に委ねられています。
※ 0.101 では ColumnHandle に変更されたようです。

TechscoreSplitManager implements com.facebook.presto.spi.ConnectorSplitManager

コネクターがデータを効率よく取得するためのパーティショニングを担うクラスです。結果として TechscorePartition オブジェクトや、TechscoreSplit オブジェクトを生成します。

TechscorePartition implements com.facebook.presto.spi.ConnectorPartition

TechscoreSplitManager によって生成されるパーティショニング情報を持つクラスです。

TechscoreSplit implements com.facebook.presto.spi.ConnectorSplit

パーティショニングに基づき決定されたデータソースへのアクセス情報を扱うクラスです。 TechscoreRecordSet オブジェクトの生成時に使用されます。

TechscoreRecordSetProvider implements com.facebook.presto.spi.ConnectorRecordSetProvider

TechscoreRecordSet オブジェクトを生成する役割を担います。

TechscoreRecordSet implements com.facebook.presto.spi.RecordSet

TechscoreSplit オブジェクト単位で生成され、TechscoreRecordCursor オブジェクトを生成する役割を担います。

TechscoreRecordCursor implements com.facebook.presto.spi.RecordCursor

データ操作に扱う「カーソル」で、 JDBC の java.sql.ResultSet と同じような役割を担います。

TechscoreConnectorConfig

カーソル専用のプロパティファイルの情報がバインディングされる POJO です。

その他、今回のサンプルとして固定のテーブル/データを定義するクラス等も必要となりますが、標準で必要となるクラスは上記の通りとなります。

Plugin とその周辺クラスの実装

JAR の Service Provider 仕様に基づき、本コネクタにおいて Plugin インターフェースの実装クラスが TechscorePrestoPlugin であることを示す必要があります。

やり方は、下記テキストファイルを用意し、その中に実装クラス名を記載するだけです。

java/main/resources/META-INF/services/com.facebook.presto.spi.Plugin

TechscorePrestoPlugin のソースです。

com.techscore.example.presto.plugin.TechscorePrestoPlugin

getServices() メソッドで、ConnectorFactory 実装クラスを要求された時に TechscoreConnectorFactory オブジェクトを生成しています。この時コンストラクタに渡されるコンフィグは Presto によってプロパティファイルから読み込まれ、setOptionalConfig() メソッドを経由してセットされています。

生成される TechscoreConnectorFactory のソースは次の通り。

com.techscore.example.presto.plugin.TechscoreConnectorFactory

create() メソッドでは、com.google.inject.Injector を使って必要な情報をインジェクションしています。

ここでインジェクトする情報は TechscoreModule を使って設定しています。

com.techscore.example.presto.plugin.TechscoreModule

configure() メソッドを見ると、何をインジェクション可能としているか明らかですね。TechscorePrestoPlugin に渡されたコンフィグはここで TechscoreConnectorConfig オブジェクトにマッピングされます。

com.techscore.example.presto.plugin.TechscoreConnectorConfig

今回のサンプルではコンフィグオブジェクトに本サイトのベース URL を持たせます。setUrlBase() メソッドのように、@Config でプロパティファイルのキーを指定することでその値がプロパティにセットされます。

プロパティファイルは次のような内容となります(配置場所は次回以降に)。

techscore.properties

そして TechscoreConnector がこれ。

com.techscore.example.presto.plugin.TechscoreConnector

前述の通り、コンストラクタに必要なオブジェクトがインジェクションされます。また、これらのオブジェクトは lombok の @Getter アノテーションによって自動生成されたゲッターメソッドによってアクセス可能となります。

今回不要なメソッドは UnsupportedOperationException をスローするよう実装しています。

次回は

長い割には序文的な記事になってしまいましたが、ここまでで概ね準備が整いました。
次回はメタデータおよびハンドル系のクラスの実装に進みます。

Comments are closed, but you can leave a trackback: Trackback URL.