このガイドラインについて
こちらのガイドラインは社内のバッチ処理スクリプト開発にあたっての、安定運用等に関わるガイドラインを公開用に書きなおしたものになります。
バッチサーバ規則
基礎項目
以下の要項を満たすことを確認する
- その他の用途で動作しているサーバ上での動作は行っていないこと
- 運用期間中に想定しうるデータ量にてOOMキラーに殺されないこと
- 想定の時間で終了すること
- データの読み込みは極力Read Replicaを見ていること
- データの書き込みによる本番サーバへの影響が見積もれていること
- 冪等性が担保されており、何度実行しても処理上の不具合は発生しないこと
- 多重実行時に不整合が発生しないこと
- エラー時の社内への通知が用意されていること
- エラー時の通知には再処理のための手順が揃っていること、もしくはそのドキュメントの場所が示されていること
- 個人ユーザー下にログや成果物を絶対に書き込んでいないこと
- その他本番サーバに影響を与える要素が無いこと
- スキーマ変更を伴う場合、関係各所のレビューをクリアしていること
- cronを利用する場合は、/etc/cron.d 配下にスケジュールファイルを配置すること
- AWSのサービスにアクセスする必要がある場合に、個人のaccess_tokenを利用していないこと
- 依存ライブラリはグローバルな環境を変更することなくインストール可能であること(bundler, virtualenv, dotenv...etc)
- 対象が大規模である、もしくは増加しうるデータの場合、処理はキュー、MapReduce等を介して複数インスタンスに分散可能であること
細かく項目を説明したいのですが、大半は当たり前な項目が多いので、かいつまんで説明していきます。
冪等性と同時実行性
大抵、バッチはコケます、なんらかの外部要因・内部要因でコケます。その時に問題になるのが、「このバッチはid1~123まで処理終わってるから二重生成してしまう」みたいな状態ですね。再度実行する際に無理やりパッチ当てるなりして再度実行するのは最悪です。
なので、こういう場合に対して、バッチを再実行する際に必ず
- 処理済みのものは処理しない
- それが難しい場合、一旦データをcleanする
ような処理を入れるようにし、何度実行しても結果の正当性が担保できるようにしましょう。
あと、例えばcrontabから5分間隔で実行するようなバッチだった場合、性能の劣化で6分かかるようになると、1分間、二重にバッチが走ることになります。
そういう場合に古い方の処理が新しい方の処理結果を上書きしないような工夫が必要です。
エラー通知
エラーが通知されないのは当たり前ですがダメです。ただ、エラーの発生のみが通知されるだけでは、見た人が対処に困ります。担当に連絡して対応を待つ、よりは、そのエラー通知を見た人がすぐ対処できるような手順書をエラーメールなりチャット通知に紐付けましょう。
弊社だと、どのサーバで、再実行手順はこれこれで、その結果の確認はここで可能です、といった最低限度の手順を通知するようになっています。
依存ライブラリ
グローバルな環境を汚染してはいけません。pythonならvirtualenv、rubyならbundlerなどを使い、必ずバッチ実行環境のためパッケージ管理を分離しましょう。出来ればDockerなどでカプセル化してると最高ですね。
あと、Goを使いましょう。Go。
これが守られないと、あるバッチではとあるライブラリを更新したくて更新したところ他のバッチがコケるなどつらい目に。
キュー、MapReduce
データが大規模になると、スケールアップでは対処できない閾値がどこかに存在していて、詰みます。その時にタスクを分散実行できるよう、対処しましょう。
分散実行を可能にするには、RabbitMQやCeleryみたいなメッセージキューを使う方法やMapReduceなどの分散実行環境がありますが、こうした環境にバッチを載せられるよう準備しましょう。
最後に
このドキュメントはまだドラフト段階ですが、他にもこんな点気をつけよう、間違ってるぞコレ、みたいな部分を指摘貰えると嬉しいです。