スケジュールの定義 (1) オーバーラップ問題
どもども、ジャナイホーです。
「プロセスの任意実行。~ もう、約束の時間を待つばっかりは、いやなの。私から、私のタイミングで、始めたいの。~」
このシリーズと関連して、スケジュール実行をしていて、よくあるのが、前のプロセスの終了が想定より時間がかかってしまい、次のプロセスが始まらない、という状況です。
こんな悩みに、どう対応したらいいのでしょうか。
やりたいこと
たとえば、平日の9:00に開始する、経理用プロセス、というものがあるとしましょう。これが通常は1時間で終わるので、余裕をもって、次の人事用のプロセスを平日の11:00開始のスケジュールを組んでいます。
たまたま、先行する経理用プロセスが11:00過ぎても終わっていない場合、11:00開始予定の人事用プロセスが、License Not Availableとか、Resource Not Availableなどでエラー終了することがあります。繁忙期で負荷が高くて想定より時間がかかった、とか、よくあることですよね。
このような場合、どうしたらよいのでしょうか。
どう対応したい?
先ず、どう対応したいか、2つのパターンが考えられると思います。
11:00開始の人事用プロセス=後発のプロセスを優先したい。
つまり、先行している経理用プロセスは、10:59で途中で(区切りが良いところで)あっても、終わらせておきたい。
人事用プロセスが一通り終わった後で、再度経理用プロセスの残りの処理を行いたい。経理用プロセス=先行のプロセスを優先的に処理をすべて終わらせて、そのあとで、正常に後発の人事用プロセスが起動されるようにしたい。
大抵は、この2つの、どちらか、というのが通常だと思います。
、が、要望は変わるものでしょう。どちらかの繁忙期、などでも、優先度は変わるかもしれません。
つまり、一概に一律で「こっち優先!」という実装して、その通りにスケジュールを組んでしまうのは、のちのちのメンテナンスの手間を考えると、回避したい、と思います。
そう考えると、、、
要件を整理すると、次のようになります。
終わったら、別のプロセスが動き出すこと
途中で止められること
再開出来ること
優先度を外から変えられること
じゃぁ、実際どうする?
では、このような要件を満たすには、どのようなソリューションが望ましいのでしょうか。ちょっと考えてみました。
スケジュール定義では、プロセスはどれも、一定周期で起動されるように、設定する。
例えば、10分おきに動くようにします。プロセスの中の実装では、「処理対象データが無ければ、何もせずに正常終了する」という仕様を組み込みます。
IsStopRequested()関数を入れた、判断ステージを各処理のあいだ、あるいは、各データのあいだ、に組み込みます。
優先度フラグをデータに含ませ、優先度の高いものから先に処理を行い、低いものはスキップする、という仕組みを入れます。
優先度の高いデータが無い場合にのみ、優先度が低いデータを処理するようにします。
セッション変数、あるいはプロセスの入力パラメータで、処理させたい優先度フラグを受け取る仕組みを入れます。
これで、先ほどの要件は満たせるプロセスが構築出来ます。。。
、、、って、めんどくセー!
、、、、ですよね。ワタシも、こんなのいちいち作ってらんないっす。
そこで登場
はい、ドン。
ワークキューとプロセステンプレートです。
今、このスケジュールのオーバラップ問題に直面されている方は、ほとんどのケースで、ワークキューを避けてきた、プロセステンプレートの存在を知らなかった、という方です。
なので、残念ながら、
外部ツールで制御しようとしたり
確実に時間内で終わらせる為に、パフォーマンスチューニングに没頭したり
スケジュールを毎回組み替えたり
任意実行の仕組みを取り入れたり
追加ライセンス購入の為の稟議書を書いたり
外部の有識者にソリューションを求めたり
ということに陥っている方を多く見かけます。
結構大変な苦労をされているのを見ると、申し訳ない気持ちでいっぱいです。。。
最初から、拡張しやすく、負荷増大にも、優先度要件変更にも耐えやすい、実装しておくことをおススメします。
最初は少し、というか、かなり、メンドクサイかもですが。。。
ワークキューを理解することを諦めないで欲しいですし、どんな小さなプロセスでも、テンプレートを使って欲しいと思っています。
そうすると、ほとんどの悩みは解決できる、あるいはあとあと苦労せずに済むのではないかなぁ、と思います。
ただそうは言っても、現状、上手く動いているものを、作り直す、なんてのは、難しいですよね。。。。ですので、これから作るものから、やってみて頂ければ、幸いです。
スケジュールの定義はこんな感じ
、、、で、そんな風にベストプラクティスに沿って作ったプロセスを、じゃぁ、とうやってスケジュール組むのが良いのでしょうか。
例えば、日中、9:00~17:00まで動かしたい。
周期的に起動させるんで、5分おきに実行させたい。
もう一つのプロセスは、少しずらして、でも、5分おきに起動させてみます。
結果として、定義されるのは、こんな感じになりますかね。
普通に行けば、9:00に開始される、「いつもは一時間程度で終わる経理用プロセス」が例えば10:05頃までかかったとして、10:08には、後発の「人事用プロセス」が起動されます。
任意実行プロセスの場合の定義の仕方は?
では、この「経理用プロセス」任意実行させたい場合、どうしたらよいでしょうか。
ユーザがメールでプロセスの実行を任意のタイミングで行いたい、ということであれば、ここでも書きましたが、「メール受信トリガープロセス」も周期スケジュールに組み込んでしまいます。
こんな感じで、一つのスケジュールの下に複数のタスクを設定します。
一つ目のタスクとして、メール受信トリガーのプロセスを指定します。
二つ目のタスクには、メインで実施したい、経理用のプロセスを指定します。
こうすると、消費するライセンスも一つだけになるので、ポーリング(メールの受信を確認するだけの処理)のためだけに、ライセンスを1つ、常時消費しなくてはならない、ということにもならずに、運用できます。
親となるスケジュールの定義にある、「初期タスク」には、「メール受信トリガーのプロセス」を指定します。
一つ目のメール受信トリガーのプロセスの「完了時のプロセス」欄には、そのあとに続いて実行したい、経理用のプロセスのタスクを指定します。
こうすることで、「経理用プロセス」のスケジュールが周期的に(例えば5分ごとに)起動され、その中のタスクが、「メール受信プロセス」→「経理用プロセス」(実処理プロセス)という順序でシーケンシャルに実行されます。
どちらのタスクも、ユーザからの依頼が来ていなければ(メールが受信していなければ)、何もせずに即座に終了します。ライセンスを無駄にずぅーっと掴みっぱなしでいることもありません。どどっといっぱい依頼が来て時間がかかり、後発の別の人事用プロセスが起動できない場合でも、経理用実処理プロセスが終了すれば、その2分後に人事用プロセスが動き出します。
ライセンスとランタイムリソースを増強させれば、何もせずとも、並列処理でスケールさせて処理時間を短くすることも可能です。
ここでは、「メールの受信」をサンプルに記載しましたが、「ファイルの受信」をトリガーにしてプロセスを起動させる場合も、同様です。
また、今回の例では、ひとつのスケジュールの下に複数タスクを定義することで、シーケンシャルにプロセスを順次実行させるように定義しましたが、複数のスケジュールにてそれぞれ、受信トリガーと実処理プロセスを分けて設定してもいいかもしれません。
スケジュールとタスクの設定の仕方、詳しい情報は、下記にあります。
Blue Prism スケジューラー ガイド(Blue Prism - Guide to the Scheduler (Japanese)_0.pdf)
まとめ
先行プロセスの遅延が後発プロセスを実行できない現象を引き起こす、というスケジュールのオーバーラップ問題には、「プロセスの周期的実行」「ワークキューを使う」「プロセステンプレートを使う」で対応してみて下さい。
保守・運用が格段に楽になります。データボリュームが増えて、負荷が増大しても柔軟に対応できます。
任意実行との組み合わせもこれで対応可能です。
メール受信トリガーのプロセス、あるいは、ファイル受信トリガーのプロセスを先行タスクとして指定することで、無駄なライセンスを消費せずに、任意のタイミングで起動をかけさせる、というニーズに対応できます。
スケジュール絡みのTipsとして、Login Agentを利用する際のTipsも下記に纏めました。
※本投稿は、別ブログで掲載・公開していた内容に加筆・修正を加え再掲載しています。