エンジニア必見!分散システムを楽にするConductor入門:居酒屋から始めるオーケストレーション
大将、ちょっと聞いてくれよ!このConductorってやつが、俺たちの仕事にめっちゃ役立ちそうなんだ。
Conductorは、複雑なワークフローを管理するための強力なオーケストレーションプラットフォームだ。マイクロサービスを組み合わせて一つの大きな処理を実行するとき、サービスの呼び出し順序や、途中でエラーが起きたときのリカバリ処理を自動でやってくれるんだ。例えるなら、居酒屋の大将が、お客さんの注文(ワークフロー)を受けて、焼き鳥担当、刺身担当、ドリンク担当(マイクロサービス)に的確に指示を出し、どのタイミングで何を作るか、もし材料が切れたらどうするか、といった全体を仕切る役目を自動でやってくれるようなもんだ。
新米
先輩、それって具体的にどう便利なんすか?全部自分でコード書けばいいんじゃないっすか?
先輩
お、いい質問だ。自分で書くこともできるが、それだとめちゃくちゃ大変になるんだ。Conductorを使うと、こんなメリットがある。
分散システムの管理が簡単になる
マイクロサービスが増えると、それぞれのサービス間の通信や状態管理が複雑になる。Conductorは、この「誰が、何を、いつ、どうやって」というのをブループリント(設計図)として定義できる。これによって、コードの可読性が上がり、管理が楽になるんだ。
障害に強いシステムが作れる
ワークフローの途中でサービスがダウンしたり、タイムアウトしたりすることがあるだろ?Conductorは、そういう場合に自動でリトライしたり、失敗した処理をやり直したりする機能を持っている。これのおかげで、エンジニアはエラーハンドリングのロジックをいちいち自分で書かなくて済むようになる。まるで、大将が「あ、あの客の注文、焼き鳥がまだ来てないな!もう一回作り直してくれ!」って自動で指示を出してくれる感じだな。
スケーラブルなシステムになる
Conductorは分散型アーキテクチャで動くから、ワークロードに応じて柔軟にスケールできる。大量のワークフローを並行して処理できるので、サービスの負荷が増えても安定して動かし続けられるんだ。
先輩
よーし、じゃあ実際にどうやって使うか見ていこうか。
Conductorの導入は、主にDockerを使って手軽に始めることができる。
Dockerコンテナを起動する
まず、docker-composeファイルを用意して、Conductorのサーバーとデータベース(Redis、Elasticsearchなど)を起動する。
version: '3'
services:
conductor-server:
image: conductor-oss/conductor-server:latest
ports:
- "8080:8080"
environment:
- CONDUCTOR_CONFIG_DIR=/app/config
volumes:
- ./config:/app/config
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.16.2
ports:
- "9200:9200"
environment:
- discovery.type=single-node
- xpack.security.enabled=false
redis:
image: redis:6.2-alpine
ports:
- "6379:6379"
このdocker-compose.ymlを使って、コンテナを起動する。
docker-compose up -d
ワークフローを定義する
次に、ワークフローの設計図(ブループリント)をJSON形式で定義する。これは、どのタスク(マイクロサービスが実行する処理)を、どのような順序で実行するかを指定するものだ。
{
"name": "payment_processing_workflow",
"version": 1,
"tasks": [
{
"name": "get_user_info",
"taskReferenceName": "get_user_info_ref",
"type": "SIMPLE",
"inputParameters": {
"userId": "${workflow.input.userId}"
}
},
{
"name": "process_payment",
"taskReferenceName": "process_payment_ref",
"type": "SIMPLE",
"inputParameters": {
"amount": "${workflow.input.amount}",
"userEmail": "${get_user_info_ref.output.email}"
}
},
{
"name": "send_confirmation_email",
"taskReferenceName": "send_email_ref",
"type": "SIMPLE",
"inputParameters": {
"email": "${process_payment_ref.output.email}",
"message": "Payment successful for amount ${process_payment_ref.output.amount}"
}
}
]
}
この例では、ユーザー情報を取得し、決済を処理し、確認メールを送るという一連の流れを定義している。
タスクを実行するワーカーを実装する
各タスク(get_user_info, process_payment, send_confirmation_email)を実際に実行するワーカー(マイクロサービス)を実装する。ここでは、JavaScript(Node.js)の例を見てみよう。
const { ConductorClient } = require('conductor-client-js');
// Conductorクライアントを初期化
const conductorClient = new ConductorClient({
serverUrl: 'http://localhost:8080/api'
});
// ワーカーを登録
conductorClient.registerWorkers([
{
taskDefName: 'get_user_info',
execute: async ({ inputData }) => {
// ユーザーIDから情報を取得する処理
console.log(`Getting user info for userId: ${inputData.userId}`);
return {
status: 'COMPLETED',
outputData: {
email: '[email protected]',
name: 'Test User'
}
};
}
},
{
taskDefName: 'process_payment',
execute: async ({ inputData }) => {
// 決済処理
console.log(`Processing payment for amount: ${inputData.amount} from user: ${inputData.userEmail}`);
return {
status: 'COMPLETED',
outputData: {
transactionId: '12345',
amount: inputData.amount,
email: inputData.userEmail
}
};
}
},
{
taskDefName: 'send_confirmation_email',
execute: async ({ inputData }) => {
// メール送信処理
console.log(`Sending confirmation email to: ${inputData.email} with message: ${inputData.message}`);
return {
status: 'COMPLETED',
outputData: {
messageStatus: 'SENT'
}
};
}
}
]);
// ワーカーを開始
conductorClient.start();
console.log('Workers started!');
このコードでは、Conductorサーバーと通信して、特定のタスクを待ち受けるワーカーを実装している。
ワークフローを開始する
最後に、定義したワークフローをAPI経由で開始する。
curl -X POST 'http://localhost:8080/api/workflow' \
-H 'Content-Type: application/json' \
-d '{
"name": "payment_processing_workflow",
"version": 1,
"input": {
"userId": "123",
"amount": 1000
}
}'
このcurlコマンドを実行すると、Conductorがブループリントに従って、一連の処理を順番に実行してくれるんだ。
大将
へぇ、すげぇな!つまり、俺が新しいメニュー(ワークフロー)を考えたら、あとは自動で各担当が動いてくれるってことか!
先輩
そういうこと!このConductorを使えば、俺たちはもっと本質的な部分、つまり「どんなサービスを作るか」に集中できるってわけさ。