並列処理の実現 

一部の R/3 レポートは夜間での処理だけでは時間が足りなくなってきています。特に大量のデータを処理するカスタマでは、 ( 品目計画実行などの ) バックグラウンド処理システムで定期的に R/3 レポートを実行する場合、非常に時間のかかることがあります。ダイアログユーザが複数のタイムゾーンにまたがっている場合は特に、このようなジョブを 夜間 に完了させることは難しくなります。

リリース 3.1G では、 R/3 短い夜 のもたらす問題の解決策として並列処理バックグラウンドジョブが用意されています。実行時間が長い R/3 レポートは並列処理で実行できるようになり、 R/3 システムの使用可能なダイアログワークプロセスに小分けして作業を行い、その後結果を終了後まとめることができます。

並列処理はバックグラウンド処理システム自体ではなく、 ABAP レポートと ABAP プログラムで実行されます。つまり、ジョブステップで実行されるレポートが並列処理用にプログラムされている場合に限り、ジョブは並列で処理されます。このようなレポートは対話式で開始される場合でも並列処理が可能です。

並列処理は非同期 RFC の特殊バリアントを使用して実行されます。ユーザ独自の並列処理アプリケーションに対して適切なバリアントの CALL FUNCTION STARTING NEW TASK DESTINATION IN GROUP キーワードだけを使用することが重要です。非同期 RFC のその他のバリアントを使用すると、正しいキーワードに組み込まれた保護機能が働かず、システムに障害が発生することになります。

汎用モジュールと ABAP キーワード

並列処理はバックグラウンドで実行されるアプリケーションレポートで実行されます。以下の汎用モジュールと ABAP キーワードを使用してユーザ独自のバックグラウンドアプリケーションで並列処理を実行できます。

以下の操作を実行できます。

CALL FUNCTION を用いた RFC コールは DIALOG タイプのワークプロセスで処理されることに注意してください。 1 つのダイアログステップの処理に関する DIALOG 制限 ( デフォルトでは 300 秒、システムプロファイルパラメータ rdisp/max_wprun_time) RFC コールにも適用されます。データを並列処理コール用に分割する際は、この制限に注意してください。

前提条件

並列処理を実行する前に、バックグラウンド処理アプリケーションと R/3 システムが以下の要件を満たしていることを確認してください。

RFC サーバグループを使用した資源管理

並列処理システムには、 R/3 システムの資源すべてが並列ジョブに使用されてしまい、他のジョブや他のユーザに性能低下の問題をもたらすような事態を発生させないための、安全機能が組み込まれています。

このような組み込まれた安全機能だけでなく、 RFC サーバグループでの資源の共有を最適化することもできます。並列処理のコンテキストでは、グループにより、特定プログラムを並列で実行するために使用される R/3 アプリケーションサーバ群が指定されます。デフォルト (DESTINATION IN GROUP DEFAULT を追加した CALL FUNCTION STARTING NEW TASK) では、このグループは資源基準を満たすすべてのサーバになります。また独自の制限を設けたグループを登録することもできます。トランザクション RZ12 ( ツール 管理 管理 ネットワーク RFC 宛先、次に RFC RFC グループ ) を使用して、グループを表示したり、更新することができます。

SPBT_INITIALIZE 汎用モジュール ( 使用される場合 ) ABAP CALL FUNCTION STARTING NEW TASK キーワードの両方に、使用予定のグループを指定する必要があります。 1 つの並列 ABAP レポートあるいはプログラム ( ジョブステップ ) には 1 つのグループしか指定できません。

メッセージと例外

コールする汎用モジュールでは、 MESSAGE キーワードではなく、エラーレポート用の例外を使用します。非同期 RFC では例外処理の制御はすべてユーザが行います。汎用モジュールにより生成された例外を CALL FUNCTION キーワードの予約済の SYSTEM_FAILURE COMMUNICATIONS_FAILURE 例外に追加するだけです。これによって並列プログラミングタスクを起動するプログラムの例外を処理できるようになります。

権限

システムプロファイルパラメータの auth/rfc_authority_check が設定されると ( 1) 、バックグラウンドジョブの権限を持つユーザが必要な RFC 権限を持つかどうかが、 CALL FUNCTION キーワードで自動的にチェックされます。 RFC 権限オブジェクトは RFC アクセス時の S_RFC 権限チェックです。権限チェックでは汎用モジュールグループ別に汎用モジュールにアクセスします。つまり、ユーザに特定グループに属する汎用モジュールを実行する権利があるかどうかがチェックされます。

汎用モジュール AUTHORITY_CHECK_RFC を使用してユーザの RFC 権限をテストできます。この汎用モジュールは、指定したグループに対する権限をユーザが持っている場合には RC = 0 を返します。汎用モジュールは権限チェックが実際に実行されるかどうかをチェックしません。

サンプルプログラム : 並列ジョブ

このサンプルプログラムは対話式で、あるいはバックグラウンド処理システムで開始された場合に、並列で実行するレポートを登録する方法を示しています。これは、 ABAP CALL FUNCTION STARTING NEW TASK 文書のオンライン文書をベースとしています。

プログラム構造

SPBT_INITIALIZE: データの宣言後、レポートは SPBT_INITIALIZE 汎用モジュールをコールします。このコールにより、プログラムは並列処理グループが有効であることと、資源が利用できることを確認します。このコールはオプションです。汎用モジュールをコールしない場合は、 R/3 システム自体が SPBT_INITIALIZE をコールして RFC サーバグループを初期化します。

汎用モジュールは利用可能なワークプロセス数を返すので、コールは処理対象となるワークパケットのサイズの決定に使用できます。たとえば、 10 個のワークプロセスを利用できる場合は、データを 10 個のパケットに分割して処理します。ただし、ジョブ用に予約されているサーバグループで作業をしている場合を除き、空きワークプロセス数がコール時とプログラムによるワークパケットの送出時までの間に変わらないという保証はありません。

また、処理予定のレコードごとに並列処理コールを行うデータを用いて実行することも当然可能です。この場合、ワークパケットサイズの最適化は行われません。

CALL FUNCTION...Loop: レポートの中心は DO ループで、ここで並列で処理される汎用モジュール (CALL FUNCTION STARTING NEW TASK DESTINATION IN GROUP) がコールされます。この例のループは単純なカウントダウンメカニズムで制御されます。本稼動レポートでは、すべてのデータが CALL FUNCTION で処理を行うために送信されるまでループを繰り返してください。

わかりやすく説明するため、この例のループではデータが不要な汎用モジュール (RFC_SYSTEM_INFO) をコールします。本稼動レポートには、処理対象のレコードあるいはレコードグループを選択するロジックをインクルードします。これらのレコードを内部テーブルにパッケージ化し、 CALL FUNCTION STARTING NEW TASK の追加 EXPORTING または TABLES 機能を使用して並列処理コールにインクルードします。

リカバリに備えて、本稼動プログラムには処理の進捗ログを記録するロジックもインクルードしてください。万が一プログラムが処理途中で異常終了した場合は、どのデータが処理済で、どのデータをレポートで再処理すべきかをユーザが判断できなければなりません。最も単純な形式の場合、このロジックは並列処理用にディスパッチされたデータを最も簡単な形式で記録し、データの単位ごとに処理が完了したものと判断するようなものになります。

CALL FUNCTION で指定したタスク名を使用して並列処理タスクを識別します。タスクからの戻りを正確に識別できるように、ディスパッチするタスクがそれぞれ固有の名称を持つようにしなければなりません。

例では、タスク管理はタスク名でカウンタを増数し、ディスパッチされたタスクのテーブルを更新します。 SPBT_GET_PP_DESTINATION を使用して、どこで並列タスクが処理されているかを特定する機能がオプションで用意されています。

RESOURCE_FAILURE 例外の処理 : 並列処理タスクがディスパッチされるごとに、 R/3 システムは以降のタスクの処理に利用できる資源数 ( ダイアログワークプロセス数 ) をカウントダウンします。このカウントは、並列処理タスクが完了すると再び増加し、プログラムに返されます。

並列処理タスクの完了までに時間がかかる場合は、並列処理資源が一時的に不足する場合があります。この場合には、 CALL FUNCTION は例外 RESOURCE_FAILURE を返します。つまり、プログラムで使用している RFC グループのすべてのダイアログワークプロセスが使用中ということです。

プログラムは、資源が利用可能になるまで待機し、エラーとなった CALL FUNCTION を再度実行する必要があります。サンプルプログラムでは、単純で合理的なフェイルセーフ待機メカニズムを使用します。このプログラムは並列処理タスクが返され、資源を解放するまで待機します。 WAIT 1 秒の初期タイムアウトの指定も行います。 CALL FUNCTION が再びエラーになると、タイムアウト時間を延長して WAIT が繰り返されます。並列タスクの完了に時間がかかると予測される場合は、タイムアウトの時間を長く設定できます。適当な回数反復した後でこの繰り返しを終了するためのコードも追加してください。

受信応答 : CALL FUNCTION キーワードは各並列処理タスクが完了するたびに FORM ルーチン RETURN_INFO の処理を開始します。この FORM ルーチンは RECEIVE キーワードを使用して並列処理の結果を取得します。この場合、 RFC_SYSTEM_INFO からの RFCSI_EXPORT 構造の内容が内部構造 INFO に設定されます。

RECEIVE は非同期実行 RFC 汎用モジュールの IMPORTING TABLE から戻されたデータを収集する必要があります。

: レポートが一覧を生成すると仮定します。 RETURN_INFO RECEIVE のような FORM ルーチンを使用して並列処理タスクが生成した一覧エントリを収集します。すべての並列タスクからデータが戻された後、レポートはソートを行うか、あるいは提示前に必要な一覧エントリの処理を継続します。

ジョブ完了の待機 : タスク管理の一部として、ジョブはすべての並列処理タスクが完了するまで待機しなければなりません。サンプルプログラムはこのために WAIT キーワードを使用し、並列処理タスク数が登録済タスク数と一致するまで待機します。この WAIT とは関係なく、 RETURN_INFO FORM ルーチンが開始されます。 WAIT 条件が正確に評価できるように、 RETURN_INFO は完了済並列処理タスク数を記録します。

この例外を処理し、処理が続行されるまで、
" あるいは処理続行を妨害する障害があることがわかるまで、
" 待機して CALL FUNCTION を繰り返す。
MESSAGE I837." すべてのサーバが現在使用中。
" 非同期 RFC コールへの応答待ち。各応答では
" ダイアログワークプロセスを再び利用可能にする必要があります。
IF EMPFNAME = SPACE.
EXCP_FLAG = 'X'.

" 最初の RESOURCE_FAILURE 処理試行。すべての
"RFC コールから処理が戻されるまで、または最高 1 秒間待機。
" 次に CALL FUNCTION を繰り返す。
WAIT UNTIL RCV_JOBS >= SND_JOBS UP TO '1' SECONDS.
ELSE.

" 2 回目の RESOURCE_FAILURE 処理試行。
WAIT UNTIL RCV_JOBS >= SND_JOBS UP TO '5' SECONDS.
"WAIT からの SY-SUBRC 0 は応答が返されたことを示す。
" そのため、資源の問題は作業負荷のために一時的に発生したものと思われる。ゼロ以外の RC
" 完了していない RFC コールが存在し、障害のある可能性があることを示します。
IF SY-SUBRC = 0.
CLEAR EXCP_FLAG.
ELSE."
応答なし
" 無限ループ処理
ENDIF.
ENDIF.
ENDCASE.
ENDDO.
...
*
*
ジョブ終了待機 : すべての RFC タスクからの応答。
*
残りの非同期応答を受信
WAIT UNTIL RCV_JOBS >= SND_JOBS.

LOOP AT TASKLIST.
WRITE:/ 'Received task:', TASKLIST-TASKNAME COLOR 1,
30 'Destination: ', TASKLIST-RFCDEST COLOR 1.
ENDLOOP.

...
*
*
このルーチンは RFC コールが完了し、返されたときに開始されます。このルーチンは RECEIVE を使用し、 RFC 汎用モジュールから、
* IMPORT
TABLE のデータを収集します。
*
* WRITE
キーワードは非同期 RFC ではサポートされないことに注意してください。一覧を生成する必要がある場合は、 RFC 汎用モジュールは
* 内部テーブルに一覧データを戻します。これにより、
*
このデータを収集し、処理の最後に一覧を出力できます。
*
FORM RETURN_INFO USING TASKNAME.


DATA: INFO_RFCDEST LIKE TASKLIST-RFCDEST.

RECEIVE RESULTS FROM FUNCTION 'RFC_SYSTEM_INFO'
IMPORTING RFCSI_EXPORT = INFO
EXCEPTIONS
COMMUNICATION_FAILURE = 1
SYSTEM_FAILURE = 2.

RCV_JOBS = RCV_JOBS + 1. "
データ受信
IF SY-SUBRC NE 0.
*
通信障害とシステム障害の処理
...

ELSE.
READ TABLE TASKLIST WITH KEY TASKNAME = TASKNAME.
IF SY-SUBRC = 0. " データ登録
TASKLIST-RFCHOST = INFO_RFCHOST.

MODIFY TASKLIST INDEX SY-TABIX.
ENDIF.

ENDIF.
...
ENDFORM