技術選定では「何のためか」を決めることが大切という話

メリークリスマス！🎄
この記事は [ラクス Advent Calendar 2022](https://qiita.com/advent-calendar/2022/rakus) の25日目の記事です。

# はじめに

この度、開発部で取り組んでいる「技術推進プロジェクト」に参画させていたくご縁があり技術選定に携わらせていただくことができました。

取り組みそのものに学びが多かったため、どのような流れで進めていったのか、ということをご説明させていただきつつ個人的な振り返りもさせていただければと思います。

# 技術推進プロジェクトについて

まずは参画させていただいたプロジェクトについて簡単にご説明いたします。
詳しくは弊社ブログに記載されておりますので、抜粋してご説明いたします。

https://tech-blog.rakus.co.jp/entry/20211216/gisui

## 目的

> これまで社内で利用していなかった技術要素を自社の開発に適合するか検証し、ビジネス要求に対して迅速に応えられるようにそなえる
>
> 参考：ラクスにおける「システムを腐敗させない組織だった技術刷新」を行う取り組み - RAKUS Developers Blog | ラクス エンジニアブログ 
> https://tech-blog.rakus.co.jp/entry/20211216/gisui

## 担当プロジェクトのメンバー構成

* インフラエンジニア
    * 2名
* アプリケーションエンジニア
    * 1名（自分）

# 取り組んだテーマ

ジョブ管理ツール

以下、Wikiによる説明。

> コンピュータ上での複数のジョブ（プログラム、バッチ処理）の起動や終了を制御したり、ジョブの実行・終了状態の監視・報告などを行うソフトウェアである。「ジョブスケジューラ」、「タスクスケジューラ」とも呼ばれる。
>
> 参考：ジョブ管理システム | Wikipedia
> https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%A7%E3%83%96%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0

## ジョブ管理の必要性

「毎日○時に○○という処理を実行したい」といったような要件を満たすために定期実行制御を行うことはよくあると思います。
その時の手段として登場する最もポピュラーなものは [cron](https://e-words.jp/w/cron.html) かと思われます。

最低限の定期実行制御であれば cron だけで十分に要件を満たせるかと思いますが、以下のような課題が出てくるかと思います。

* アプリケーションの規模が大きくなってくると制御対象の処理が増えてきて煩雑化する
* 処理の実行タイミングが重なることによって断続的にサーバ高負荷を発生してしまう
* 前処理の成功や失敗を考慮しなければならない依存関係のある処理を定期実行制御しようとすると工夫が必要になる
* 処理に失敗した時の救済措置を別途考慮しなければならない

これらの辛みをシステムで解決してくれるのがジョブ管理ツールとなります。

# ツールの選定方針

ジョブ管理ツールといえど、ツールによって得意領域が千差万別です。
自分たちの課題を解決する上でマッチしているものや既存システムに導入しやすいといった軸で選定していくことが自然かと思います。

以降では、検証対象とするツールをどのように選定したのかをご説明します。

## 課題の明確化

そもそも、自分たちが何故ジョブ管理ツールを必要としているのか、ということを明確化してみました。

技術推進プロジェクトの特性上、担当するプロダクトにおける目下の課題が取り上げられることは少なく、いずれのテーマも、将来的に必要になるであろう技術領域がピックアップされます。

そのため、漠然とした課題を我が事として捉え、具体的なユースケースに落とし込む必要があります。

### なぜ課題なのか

基本的なことですが、目的をしっかりと認識してからスタートすることが重要です。

課題を正しく捉えられおらず、本質的な問題を誤って認識してしまうと選択した対策も的を得ないものになってしまいます。
その結果、本質的な課題が解消されない手段だけが運用に残ってしまい、かえって非効率になってしまうということにもなりかねません。

そのため、上記にあるようなジョブ管理ツールの必要性が「自分たちにとって共感できるか」ということを冷静に分析する必要があります。

### 課題を抱えている対象は誰なのか

ジョブ管理ツール無しで運用を続けていくと様々な辛みがあることは上記でわかりましたが、上記の辛さがあるのはシステムを運用する側だけなのか、ということを振り返りました。

まずは、システムの運用を行う上での関係者（ステークホルダ）を「漏れなく・ダブりなく（[MECE](https://ja.wikipedia.org/wiki/MECE)）」洗い出しました。

* 影響を受ける関係者
    * 自社
    * 顧客
    * ビジネスパートナー
    * 一般の方

上記がジョブ管理ツールの無い運用により課題を抱える対象であると捉えました。

### 対象が伴う辛さは何なのか

対象者を絞り込めたら、それぞれの対象が伴う辛さが何なのかを考えてみます。

ジョブ管理ツールを採用する目的は自社のメリットのために採用しているように思えますが、深堀してみると以外と見えてこなかったような課題感が出てきました。

* 自社にとっての辛さ
    * 人件費
        * メンテナンス工数がかかる
        * トラブル時の調査工数がかかる
    * システムコスト
        * 過剰なリソースを積まなければならない
        * 一斉処理による負荷集中
        * 電力の急激な上昇
* 顧客にとっての辛さ
    * 処理遅延
        * ユーザビリティの低下
        * 信頼性の低下
* ビジネスパートナーへの影響
    * 他社機器への負荷
        * 信頼性の低下
        * コストの増加
* 一般の方への影響
    * 環境負荷
        * 電力消費に伴うCO2の排出量が増加する

洗い出した課題感を解消していくことが目的で、その手段としてジョブ管理ツールを利用してみよう、となります。

ここまでくれば、自分たちがジョブ管理ツールを利用する意義が明確になり、導入後に「なんで必要なんだっけ？無くてもよかったんじゃない？」といった悲しい結末にはならなくなりました。

### 課題が解決された先にある「あるべき姿」はどんな状態なのか

ジョブ管理ツールを用いて解決したい課題と対象者の辛さが明確になりましたので、課題が解決された未来ではどういう状態になっているのかを設定します。

あるべき姿の状態にはいくつかの段階があり、すべてを完璧に達成することはプロジェクトの期間的な事情もあり難しそうだったので、優先度をつけてみました。

* 最優先
    * 顧客のユーザビリティが低下しない
    * 定期実行処理の仕様リソースが最適化されている
    * 自社環境での定期実行処理が負荷分散されている
* 優先
    * 他社システムと連携する定期実行処理が負荷分散されている
    * 定期実行処理が異常終了しても自動で再実行される
    * 定期実行処理の進行状況が把握できる
* できれば
    * 移行が簡単にできる
    * メンテナンスが簡単にできる

上記の目標に向かってツールの選定や検証を行っていきます。

## 求める要件の設定

ツールを採用する意義は明確になりましたので、次はどんなツールを選ぶべきかを考えていきます。

[IPAの非機能要求グレード](https://www.ipa.go.jp/sec/softwareengineering/std/ent03-b.html) に記載されている非機能要求一覧の項目をベースに調査を行いました。

* IPAが定義する非機能要求の項目一覧
    * 可用性
    * 性能／拡張性
    * 運用／保守性
    * 移行性
    * セキュリティ
    * システム環境／エコロジー

https://www.ipa.go.jp/sec/softwareengineering/std/ent03-b.html

今回は上記の項目に該当する具体的な要求をブレスト的に挙げていく方法でしたが、IPAが定める非機能要求グレードの検討手順はもっと複雑で時間がかかるもののようです。
この辺りは全く触れられていないので、機会があれば是非見ておきたいと思います。

求める要件を定めているうちに非機能だけでなく、機能面でも要求を満たす必要がありそうだったので、さらに項目を拡張し、最終的には以下のようになりました。

* 機能
  * バッチに優先度付けできる
  * 実施日時を指定できる
  * 実施時間(周期)を指定できる
  * 実行時のデータ量を指定できる
  * client側の操作をトリガーにできる
  * 上記条件の組み合わせができる
  * パイプライン制御ができる
* 非機能
  * 可用性
    * 処理単体：バッチが異常終了しても自動で再実行できる。
    * システム全体：バッチ処理再実行までの時間が5分以内
    * システム全体：バッチ処理システムが停止しない
  * 性能／拡張性
    * 顧客のユーザビリティが低下しない(既存と比べて処理時間が長くならない)
    * バッチ処理の使用リソースが最適化されている。
    * バッチの実行時間がxx以内
    * バッチの待ち時間がxx以内
    * バッチサーバのスケールアウトがオンラインで可能
    * バッチサーバの削除がオンラインで可能
    * バッチサーバのスケールアップがオンラインで可能
    * バッチサーバのスペックダウンがオンラインで可能
    * バッチの新規追加・削除がオンラインで可能
  * 運用／保守性
    * バッチの進行状況が把握できる。(キューの状況も)
    * 調査が容易にできる。
    * バッチの停止ができる
    * バッチサーバの停止ができる
    * バッチ異常時の通知ができる
    * バッチサーバのアップデートがオンラインでできる
    * サポート体制が整っている
  * 移行性
    * 移行が簡単にできる。
  * セキュリティ
    * ポリシーが設定できる(部門でロールを分けるとか)
    * アップデートが頻繁(品質が高い・信頼できるか)

## 求める要件の重みづけ

様々な要件が出てきましたが、必ずしもすべての要件を満たす必要はなく、ものによっては優先度が低いものも混ざっていたことから、各項目を重みづけしました。

|要件 | 優先度|
|--- | ---|
|バッチに優先度付けできる | 高|
|実施日時を指定できる | 高|
|実施時間(周期)を指定できる | 高|
|実行時のデータ量を指定できる | 低|
|client側の操作をトリガーにできる | 高|
|上記条件の組み合わせができる | 高|
|パイプライン制御ができる | 低|
| … | …|

これにより、ジョブ管理ツールを選定する際に、優先度の高い要件が満たしていれば全ての要件は満たせていなくてもよい、といった採用の判断軸ができました。

# ツールの選定

ここまで長かったですが、いよいよツールの選定となります。

プロジェクトメンバー各々で書籍やWebの情報を元に、世間的に利用されているジョブ管理ツールはどんなものがあるのかを調査しました。

プロジェクトメンバーとして選出されたものの、私自身はほとんど前提知識がなかったので、調査にあたっては手当たり次第に様々なWebの記事を参考にさせていただきました。
個人的にはモノタロウさんの以下の記事を特に参考にさせていただきました。

https://tech-blog.monotaro.com/entry/2018/03/02/183551

メンバー間の調査により、最終的には以下のツールを深堀調査の対象とすることにしました。

* [Sidekiq](https://sidekiq.org/)
* [Resque](https://github.com/resque/resque)
* [Delayed Job](https://github.com/collectiveidea/delayed_job)
* [shoryuken](https://github.com/ruby-shoryuken/shoryuken)
* [Dataflow](https://cloud.google.com/dataflow?hl=ja)（[Apache Beam](https://beam.apache.org/)）
* [Amazon Kinesis](https://aws.amazon.com/jp/kinesis/)
* [AWS Lambda](https://aws.amazon.com/jp/lambda/)
* [Azure Event Hubs](https://azure.microsoft.com/ja-jp/products/event-hubs/)
* [Azure Batch](https://azure.microsoft.com/ja-jp/products/batch)
* [Hadoop](https://hadoop.apache.org/)
* [Rundeck](https://www.rundeck.com/)
* [Digdag](https://www.digdag.io/)
* [Apache Airflow](https://airflow.apache.org/)
* [Luigi](https://github.com/spotify/luigi)
* [JP1](https://www.hitachi.co.jp/Prod/comp/soft1/jp1/index.html)
* [hinemos](https://www.hinemos.info/)

# 星取表の作成

上記で選定したツールに対して、公式ドキュメント等を読みながら要件を満たせているかをひたすら調査していくわけですが、各ツールの要件達成状態を比較できるように調査結果は星取表でまとめていきました。

|要件 | Sidekiq | Resque | Airflow|
|--- | --- | --- | ---|
|バッチに優先度付けできる | 〇 | △ | 〇|
|実施日時を指定できる | 〇 | 〇 | 〇|
|実施時間(周期)を指定できる | 〇 | 〇 | 〇|
|実行時のデータ量を指定できる | △ | × | ?|
|client側の操作をトリガーにできる | 〇 | 〇 | 〇|
|上記条件の組み合わせができる | △ | × | ?|
|パイプライン制御ができる | 〇 | × | 〇|

ここでは表せていませんが、要件を満たせているものについては、その根拠を示すドキュメントのURLを提示するようにして、後から振り返れるようにしました。

# ツールの選定

完成した星取表から優先度の高い要求が満たせている数が多いツールを選定していきました。

調査をしてみてわかったこととしては今回提示した要求はジョブ管理ツールの基本的な機能の部分が大きかった模様でした。
そのため、ほとんどのツールが優先度の高いよう要求を満たせていました。
結果的に、同率一位になったツールがいくつか出てきてしまい、判断に迷ってしまうという誤算が発生してしまいました。（トレンドを抑えておくって重要・・・）

最終的には、以下の理由から「Airflow」を検証用のツールとして選定することにしました。

* 公式ドキュメントの重厚さ
* 日本語での解説の多さ
* AWS に [Amazon MWAA](https://aws.amazon.com/jp/managed-workflows-for-apache-airflow/) というマネージドサービスがある
    * 将来的にシステムをスケールアウトしやすい

https://aws.amazon.com/jp/managed-workflows-for-apache-airflow/

# 調査対象ツールの検証

実際にツールを使ってみて要件を満たせるように実装し評価していくフェーズになりますが、以降についてはこれから着手していく予定ですので別の機会で説明できればと思います。

# 苦労話や失敗談

最終的に選定したツールは「Airflow」になりましたが、最初は優先度の高い要求をすべて満たすことができていた「Dataflow（Apache Beam）」を検証対象としておりました。

しかし、実際使ってみると、要件を満たすためには「Dataflow（Apache Beam）」だけでなく、GCPのそのほかのサービスと組み合わせなければならないことがわかりました。

そもそも、「Dataflow（Apache Beam）」は要求を満たすにはオーバースペック過ぎた印象もあったので、早めに状況を整理して方向転換できたのはよかったかと思います。

# おわりに

技術選定で最も時間がかかる工程は「調査対象のツールの検証作業」になると思われます。
「これじゃない感」による手戻りをなるべく減らすためにも、課題感や要求の具体化にしっかりと時間を取って整理しておくことが重要であると感じました。

現在、ツールの検証作業実施中ではありますが、検証が完了した際は、最初に掲げた課題感が解消され、あるべき姿を達成できているかを改めて振り返ってみたいと思います。