(本記事は Heroku Advent Calendar 2019 11日目の記事になります)
はじめに
Talend Open Studio for Data Integrationは、GUIベースでデータ連携プログラムを作成できる非常に利便性の高いソフトウェアとして公開されております。
このソフトウェアで作成したジョブは、jarファイルとしてエクスポートして手元で実行させることも可能です。
エクスポートしたjarファイルを実行させる環境としては、ローカルやオンプレはなるべく避けたいところで、何かしらのクラウドサービス上にデプロイして実行させたい...と思うことが多いのではないでしょうか。
そんなわけで、本記事ではエクスポートしたTalendジョブをHerokuにデプロイして実行させる方式について検討したことを紹介します。
Heroku側でのアプリケーション構成
今回試した構成は、このようなものです。
(補足)
今回はNode.jsから起動させる方式にしていますが、もちろんJavaアプリケーションとしてTalendジョブを組み込むようにしても良いと思います。
実際にこちらのブログで紹介されています。
今回は
- TalendジョブはDev属性以外の人が作る(コードは書けないけど、ツールは使える等)
- 作ったジョブからエクスポートしたjarを受け取って組み込む
と、分担してみるあたりの検討も兼ねて、このような構成にしてみました。
サンプルとするTalendジョブ
今回試すTalendジョブは非常にシンプルなものです。
- salesforce(DE環境)に接続する
- ユーザをクエリする(1件だけ取得する)
- そのユーザに対して、FeedItemを作成する
- プラットフォームイベントを作成する
- salesforce側では、プラットフォームイベントを受信するとプロセスビルダーが起動してカスタム通知を送信するようにしています
...といった具合です。
Talend上で作成したジョブをエクスポートするとzipファイルが作成されます。
そのzipファイルを解凍すると、中にjarファイルと起動用のshファイルがありますのでこれを利用します。
なお、shファイルは実行可能となるようにしておいてください(念のため)
Herokuへの実装
<前提>
Heroku Appを事前に用意しておきます。以下、try-boot-talend
というHeroku Appが存在する前提で進みます。
使用するbuildpack
今回使用するbuilpackは以下2つです。
heroku/jvm
heroku/nodejs
nodejsアプリを動かすためのheroku/nodejs
の他に、メインとなるTalendジョブを動かすためのheroku/jvm
も使用します。
$ heroku buildpacks:add heroku/jvm -a try-boot-talend
$ heroku buildpacks:add heroku/nodejs -a try-boot-talend
使用するAddon
今回使用するAddonは以下になります。
メッセージング基盤を提供するaddonになります。実際にはRabbitMQをSaaSとして提供しています。
※合わせてどうぞ -> 新人プログラマに知ってもらいたいRabbitMQ初心者の入門の入門
$ heroku addons:create cloudamqp:lemur -a try-boot-talend
heroku環境変数
今回は1つだけ追加します。RabbitMQへのQueueのキーを指定しておきます。
$ heroku config:set MSG_QUEUE_TOPIC_EXEC_TALEND="talend" -a try-boot-talend
Talendジョブを起動するためのプログラム
大体こんな感じです。
'use strict';
/**
*
*/
const child = require('child_process');
// AMQP
const amqp = require('amqplib');
const amqp_url = process.env.CLOUDAMQP_URL || "amqp://localhost";
const open = amqp.connect(amqp_url);
/**
*
*/
function start() {
//
open.then( con => {
return con.createChannel();
}).then( channel => {
const topic = process.env.MSG_QUEUE_TOPIC_EXEC_TALEND;
return channel.assertQueue(topic).then( ok => {
return channel.consume(topic, async (msg) => {
if (msg !== null) {
const data = JSON.parse(msg.content.toString('utf8'));
console.log(data);
await exec_job(data);
channel.ack(msg);
}
})
})
});
}
/**
*
*/
function exec_job (data) {
return new Promise((resolve, reject) => {
let res;
let spawned = child.spawn('/app/custom_notification/custom_notification_run.sh', [data.message])
.on('close', (code) => {
if (code === 0) {
console.log('--------------------- success');
resolve(res);
} else {
console.log('--------------------- failed');
reject(res);
}
});
});
}
//
start();
ほぼamqp.nodeのREADMEにあるサンプルを流用したものになります。
つまるところは、CloudAMQPのQueueをsubscribeしておいて、何かメッセージがきたらそれに反応して処理を実行する、といったものになります。
ここまで完了したら、worker dynoを起動させておきましょう。
$ heroku ps:scale worker=1 -a try-boot-talend
試しに実行してみる
RabbitMQのQueueにメッセージを送ってみましょう
Heroku Appの管理画面からCloudAMQPの管理画面を起動します。
さらにRabbitMQ管理画面を起動します。
talend
というQueueが作成されているのが確認できます。(たぶん)
そのQueueに対して、メッセージを発行してみましょう。
このQueueを購読しているworkerが反応してtalend jobを起動します。
その結果としてChatterやカスタム通知にメッセージが作成されました!
(追加)
今回は、RabbitMQの管理画面からメッセージを発行しましたが、ある特定のエンドポイントにPOSTされると、RabbitMQのQueueにメッセージを発行するWebアプリを用意すると、色々と利便性が高まると思います。
また、本記事ではTalendジョブに関するjarファイル群はリポジトリ内に格納しましたが、例えばS3に格納しておいてHeroku Appのビルド内でS3からダウンロード&展開...という具合にしたりすると、もう少しスマートになるかもな、と(ぼんやりと)考えてます。
ちなみに、今回のサンプルは こちら でも確認できます。
おしまい
Talendジョブを実行させるための環境としてHerokuも活用できるのではないか?という検証でした。可能性はあるにせよ、まだ悩ましいところ(Talendジョブのソースコードをどう管理するか?などHeroku以外の部分も...)はありますので、継続して検討していきたいと思います。
それでは引き続きHerokuとキャッキャウフフして、さらなる高みを目指しましょう!
(知らんけど)