Spring Cloudデータフローを使用したETL

Spring Cloud Data Flowを使用したETL

1. 概要

Spring Cloud Data Flowは、リアルタイムのデータパイプラインとバッチプロセスを構築するためのクラウドネイティブツールキットです。 Spring Cloud Data Flowは、単純なインポート/エクスポート、ETL処理、イベントストリーミング、予測分析など、さまざまなデータ処理のユースケースですぐに使用できます。

このチュートリアルでは、JDBCデータベースからデータを抽出し、それを単純なPOJOに変換して、MongoDBにロードするストリームパイプラインを使用したリアルタイムの抽出変換と読み込み(ETL)の例を学習します。

2. ETLおよびイベントストリーム処理

ETL –抽出、変換、およびロード–は、一般に、複数のデータベースおよびシステムから共通のデータウェアハウスにデータをバッチロードするプロセスと呼ばれていました。 このデータウェアハウスでは、システムの全体的なパフォーマンスを損なうことなく、大量のデータ分析処理を実行できます。

ただし、新しいトレンドがこれを行う方法を変えています。 ETLには、データをデータウェアハウスおよびデータレイクに転送する役割があります。

現在、これはstreams in an event-stream architecture with the help of Spring Cloud Data Flowで実行できます。

3. Spring Cloudのデータフロー

Spring Cloud Data Flow(SCDF)を使用すると、開発者は2つのフレーバーでデータパイプラインを作成できます。

  • Spring Cloud Streamを使用した長寿命のリアルタイムストリームアプリケーション

  • Spring Cloud Taskを使用した短命のバッチタスクアプリケーション

この記事では、Spring CloudStreamをベースにした最初の長寿命のストリーミングアプリケーションについて説明します。

3.1. Spring Cloud Streamアプリケーション

SCDFストリームパイプラインは、whereeach step is an application built in Spring Boot style using the Spring Cloud Stream micro-framework.のステップで構成されています。これらのアプリケーションは、ApacheKafkaやRabbitMQなどのメッセージングミドルウェアによって統合されています。

これらのアプリケーションは、ソース、プロセッサ、およびシンクに分類されます。 ETLプロセスと比較すると、ソースは「抽出」、プロセッサは「トランス」、シンクは「ロード」部分と言えます。

場合によっては、パイプラインの1つ以上のステップでアプリケーションスターターを使用できます。 つまり、ステップに新しいアプリケーションを実装する必要はありませんが、代わりに、すでに実装されている既存のアプリケーションスターターを構成します。

アプリケーションスターターのリストはhereで見つかりました。

3.2. Spring Cloud Data Flow Server

The last piece of the architecture is the Spring Cloud Data Flow Server。 SCDFサーバーは、Spring Cloud Deployer仕様を使用してアプリケーションとパイプラインストリームの展開を行います。 この仕様は、Kubernetes、Apache Mesos、Yarn、Cloud Foundryなどの最新のランタイムに展開することにより、SCDFクラウドネイティブフレーバーをサポートします。

また、ストリームをローカル展開として実行できます。

SCDFアーキテクチャの詳細については、hereを参照してください。

4. 環境設定

開始する前に、choose the pieces of this complex deploymentにする必要があります。 定義する最初の部分はSCDFサーバーです。

テストの場合、we’ll use SCDF Server Local for local development。 本番環境のデプロイでは、後でSCDF Server Kubernetesなどのクラウドネイティブランタイムを選択できます。 サーバーランタイムhereのリストを見つけることができます。

それでは、このサーバーを実行するためのシステム要件を確認しましょう。

4.1. システム要求

SCDFサーバーを実行するには、2つの依存関係を定義して設定する必要があります。

  • メッセージングミドルウェア、および

  • RDBMS。

メッセージングミドルウェアの場合、パイプラインストリーム定義を格納するためのwe’ll work with RabbitMQ, and we choose PostgreSQL as an RDBMS

RabbitMQを実行するには、最新バージョンhereをダウンロードし、デフォルト構成を使用してRabbitMQインスタンスを起動するか、次のDockerコマンドを実行します。

docker run --name dataflow-rabbit -p 15672:15672 -p 5672:5672 -d rabbitmq:3-management

最後のセットアップ手順として、デフォルトポート5432でPostgreSQL RDBMSをインストールして実行します。 その後、次のスクリプトを使用して、SCDFがそのストリーム定義を保存できるデータベースを作成します。

CREATE DATABASE dataflow;

4.2. Spring Cloud Data Flow Server Local

SCDFサーバーローカルを実行するために、サーバーusing docker-compose,を起動するか、Javaアプリケーションとして起動するかを選択できます。

Here, we’ll run the SCDF Server Local as a Java application.アプリケーションを構成するには、構成をJavaアプリケーションパラメーターとして定義する必要があります。 システムパスにJava8が必要です。

jarと依存関係をホストするには、SCDFサーバーのホームフォルダーを作成し、SCDFサーバーローカル配布をこのフォルダーにダウンロードする必要があります。 SCDFサーバーローカルhereの最新のディストリビューションをダウンロードできます。

また、libフォルダーを作成し、そこにJDBCドライバーを配置する必要があります。 PostgreSQLドライバーの最新バージョンはhereで入手できます。

最後に、SCDFローカルサーバーを実行してみましょう。

$java -Dloader.path=lib -jar spring-cloud-dataflow-server-local-1.6.3.RELEASE.jar \
    --spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/dataflow \
    --spring.datasource.username=postgres_username \
    --spring.datasource.password=postgres_password \
    --spring.datasource.driver-class-name=org.postgresql.Driver \
    --spring.rabbitmq.host=127.0.0.1 \
    --spring.rabbitmq.port=5672 \
    --spring.rabbitmq.username=guest \
    --spring.rabbitmq.password=guest

次のURLを確認することで、実行されているかどうかを確認できます。

4.3. Spring Cloud Data Flow Shell

SCDFシェルはcommand line tool that makes it easy to compose and deploy our applications and pipelinesです。 これらのシェルコマンドは、Spring Cloud Data Flow ServerREST API上で実行されます。

jarの最新バージョンをSCDFホームフォルダ(利用可能なhere.)にダウンロードします。ダウンロードが完了したら、次のコマンドを実行します(必要に応じてバージョンを更新します)。

$ java -jar spring-cloud-dataflow-shell-1.6.3.RELEASE.jar
  ____                              ____ _                __
 / ___| _ __  _ __(_)_ __   __ _   / ___| | ___  _   _  __| |
 \___ \| '_ \| '__| | '_ \ / _` | | |   | |/ _ \| | | |/ _` |
  ___) | |_) | |  | | | | | (_| | | |___| | (_) | |_| | (_| |
 |____/| .__/|_|  |_|_| |_|\__, |  \____|_|\___/ \__,_|\__,_|
  ____ |_|    _          __|___/                 __________
 |  _ \  __ _| |_ __ _  |  ___| | _____      __  \ \ \ \ \ \
 | | | |/ _` | __/ _` | | |_  | |/ _ \ \ /\ / /   \ \ \ \ \ \
 | |_| | (_| | || (_| | |  _| | | (_) \ V  V /    / / / / / /
 |____/ \__,_|\__\__,_| |_|   |_|\___/ \_/\_/    /_/_/_/_/_/


Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help".
dataflow:>

最後の行に「dataflow:>”」の代わりに「server-unknown:>”」が表示される場合は、ローカルホストでSCDFサーバーを実行していません。 この場合、次のコマンドを実行して別のホストに接続します。

server-unknown:>dataflow config server http://{host}

これで、シェルがSCDFサーバーに接続され、コマンドを実行できます。

シェルで最初に行う必要があるのは、アプリケーションスターターをインポートすることです。 Spring Boot2.0.xでRabbitMQ + Mavenの最新バージョンhereを見つけ、次のコマンドを実行します(ここでも、必要に応じてバージョンを更新します。ここでは「Darwin-SR1」)。

$ dataflow:>app import --uri http://bit.ly/Darwin-SR1-stream-applications-rabbit-maven

インストールされたアプリケーションを確認するには、次のシェルコマンドを実行します。

$ dataflow:> app list

その結果、インストールされているすべてのアプリケーションを含むテーブルが表示されます。

また、SCDFは、Floという名前のグラフィカルインターフェイスを提供しており、このアドレスhttp://localhost:9393/dashboardでアクセスできます。 ただし、その使用はこの記事の範囲外です。

5. ETLパイプラインの作成

それでは、ストリームパイプラインを作成しましょう。 これを行うために、JDBCソースアプリケーションスターターを使用して、リレーショナルデータベースから情報を抽出します。

また、情報構造を変換するためのカスタムプロセッサと、データをMongoDBにロードするためのカスタムシンクを作成します。

5.1. 抽出-抽出用のリレーショナルデータベースの準備

crmという名前のデータベースとcustomerという名前のテーブルを作成しましょう。

CREATE DATABASE crm;
CREATE TABLE customer (
    id bigint NOT NULL,
    imported boolean DEFAULT false,
    customer_name character varying(50),
    PRIMARY KEY(id)
)

フラグimportedを使用していることに注意してください。このフラグは、すでにインポートされているレコードを格納します。 必要に応じて、この情報を別のテーブルに保存することもできます。

それでは、いくつかのデータを挿入しましょう。

INSERT INTO customer(id, customer_name, imported) VALUES (1, 'John Doe', false);

5.2. 変換– JDBCフィールドをMongoDBフィールド構造にマッピングする

変換ステップでは、フィールドcustomer_nameをソーステーブルから新しいフィールドnameに簡単に変換します。 ここで他の変換を行うこともできますが、例は短くしておきましょう。

To do this, we’ll create a new project with the name customer-transform.これを行う最も簡単な方法は、Spring Initializrサイトを使用してプロジェクトを作成することです。 Webサイトにアクセスしたら、グループとアーティファクト名を選択します。 それぞれcom.customercustomer-transform,を使用します。

これが完了したら、「Generate Project」ボタンをクリックしてプロジェクトをダウンロードします。 次に、プロジェクトを解凍してお気に入りのIDEにインポートし、次の依存関係をpom.xmlに追加します。


    org.springframework.cloud
    spring-cloud-stream-binder-rabbit

これで、フィールド名変換のコーディングを開始する準備が整いました。 これを行うには、アダプタとして機能するCustomerクラスを作成します。 このクラスは、setName()メソッドを介してcustomer_nameを受け取り、getNameメソッド.を介してその値を出力します。

@JsonProperty annotationsは、JSONからJavaへの逆シリアル化中に変換を行います。

public class Customer {

    private Long id;

    private String name;

    @JsonProperty("customer_name")
    public void setName(String name) {
        this.name = name;
    }

    @JsonProperty("name")
    public String getName() {
        return name;
    }

    // Getters and Setters
}

プロセッサは、入力からデータを受信し、変換を行い、結果を出力チャネルにバインドする必要があります。 これを行うためのクラスを作成しましょう。

import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Processor;
import org.springframework.integration.annotation.Transformer;

@EnableBinding(Processor.class)
public class CustomerProcessorConfiguration {

    @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
    public Customer convertToPojo(Customer payload) {

        return payload;
    }
}

上記のコードでは、変換が自動的に行われることがわかります。 入力はJSONとしてデータを受け取り、Jacksonはsetメソッドを使用してデータをCustomerオブジェクトに逆シリアル化します。

反対は出力の場合で、データはgetメソッドを使用してJSONにシリアル化されます。

5.3. ロード– MongoDBのシンク

変換ステップと同様に、we’ll create another maven project, now with the name customer-mongodb-sink。 ここでも、Spring Initializrにアクセスし、グループの場合はcom.customerを選択し、アーティファクトの場合はcustomer-mongodb-sinkを選択します。 次に、依存関係の検索ボックスにMongoDB *“ *と入力して、プロジェクトをダウンロードします。

次に、解凍​​してお気に入りのIDEにインポートします。

次に、customer-transformプロジェクトと同じ追加の依存関係を追加します。

次に、このステップで入力を受け取るために、別のCustomerクラスを作成します。

import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection="customer")
public class Customer {

    private Long id;
    private String name;

    // Getters and Setters
}

Customerをシンクするために、CustomerRepositoryを使用して顧客エンティティを保存するListenerクラスを作成します。

@EnableBinding(Sink.class)
public class CustomerListener {

    @Autowired
    private CustomerRepository repository;

    @StreamListener(Sink.INPUT)
    public void save(Customer customer) {
        repository.save(customer);
    }
}

そして、この場合のCustomerRepositoryは、Spring DataからのMongoRepositoryです。

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CustomerRepository extends MongoRepository {

}

5.4. ストリーム定義

ここで、both custom applications are ready to be registered on SCDF Server.これを実現するには、Mavenコマンドmvn installを使用して両方のプロジェクトをコンパイルします。

次に、Spring Cloud Data Flow Shellを使用してそれらを登録します。

app register --name customer-transform --type processor --uri maven://com.customer:customer-transform:0.0.1-SNAPSHOT
app register --name customer-mongodb-sink --type sink --uri maven://com.customer:customer-mongodb-sink:jar:0.0.1-SNAPSHOT

最後に、アプリケーションがSCDFに保存されているかどうかを確認し、シェルでapplicationlistコマンドを実行します。

app list

その結果、結果の表に両方のアプリケーションが表示されるはずです。

5.4.1. ストリームパイプラインドメイン固有言語-DSL

DSLは、アプリケーション間の構成とデータフローを定義します。 SCDF DSLは簡単です。 最初の言葉では、アプリケーションの名前を定義し、続いて構成を定義します。

また、構文はUnixに着想を得たPipeline syntaxであり、「パイプ」とも呼ばれる垂直バーを使用して、複数のアプリケーションを接続します。

http --port=8181 | log

これにより、ポート8181で提供されるHTTPアプリケーションが作成され、受信したボディペイロードがログに送信されます。

それでは、JDBCソースのDSLストリーム定義を作成する方法を見てみましょう。

5.4.2. JDBCソースストリーム定義

JDBCソースの主要な構成はqueryupdateです。 query will select unread records while update will change a flag to prevent the current records from being reread.

また、30秒の固定遅延でポーリングし、最大1000行をポーリングするようにJDBCソースを定義します。 最後に、ドライバー、ユーザー名、パスワード、接続URLなどの接続の構成を定義します。

jdbc 
    --query='SELECT id, customer_name FROM public.customer WHERE imported = false'
    --update='UPDATE public.customer SET imported = true WHERE id in (:id)'
    --max-rows-per-poll=1000
    --fixed-delay=30 --time-unit=SECONDS
    --driver-class-name=org.postgresql.Driver
    --url=jdbc:postgresql://localhost:5432/crm
    --username=postgres
    --password=postgres

その他のJDBCソース構成プロパティはhereにあります。

5.4.3. 顧客MongoDBシンクストリームの定義

customer-mongodb-sinkapplication.propertiesで接続構成を定義しなかったため、DSLパラメータを使用して構成します。

このアプリケーションは完全にMongoDataAutoConfiguration.に基づいています。他の可能な構成を確認できます。here.基本的に、spring.data.mongodb.uriを定義します。

customer-mongodb-sink --spring.data.mongodb.uri=mongodb://localhost/main

5.4.4. ストリームを作成してデプロイする

まず、最終的なストリーム定義を作成するには、シェルに戻って次のコマンドを実行します(読みやすくするために改行なしで挿入されています)。

stream create --name jdbc-to-mongodb
  --definition "jdbc
  --query='SELECT id, customer_name FROM public.customer WHERE imported=false'
  --fixed-delay=30
  --max-rows-per-poll=1000
  --update='UPDATE customer SET imported=true WHERE id in (:id)'
  --time-unit=SECONDS
  --password=postgres
  --driver-class-name=org.postgresql.Driver
  --username=postgres
  --url=jdbc:postgresql://localhost:5432/crm | customer-transform | customer-mongodb-sink
  --spring.data.mongodb.uri=mongodb://localhost/main"

このストリームDSLは、jdbc-to-mongodbという名前のストリームを定義します。 次に、we’ll deploy the stream by its name

stream deploy --name jdbc-to-mongodb

最後に、利用可能なすべてのログの場所がログ出力に表示されます。

Logs will be in {PATH_TO_LOG}/spring-cloud-deployer/jdbc-to-mongodb/jdbc-to-mongodb.customer-mongodb-sink

Logs will be in {PATH_TO_LOG}/spring-cloud-deployer/jdbc-to-mongodb/jdbc-to-mongodb.customer-transform

Logs will be in {PATH_TO_LOG}/spring-cloud-deployer/jdbc-to-mongodb/jdbc-to-mongodb.jdbc

6. 結論

この記事では、Spring Cloud DataFlowを使用したETLデータパイプラインの完全な例を見てきました。

最も注目すべきは、アプリケーションスターターの構成を確認し、Spring Cloud Data Flow Shellを使用してETLストリームパイプラインを作成し、データの読み取り、変換、書き込み用のカスタムアプリケーションを実装したことです。

いつものように、サンプルコードはin the GitHub project.で見つけることができます