The purpose of this page is to illustrate how the qRFC framework functions and how qRFCs are related to tRFCs. It's main purpose is not as a troubleshooting resource but a knowledge resource.
Like tRFCs, queued RFCs (qRFCs) are a an abstracted type of RFC call. They are not physical RFC calls like synchronous and asynchronous RFC calls. qRFCs are an extension on the tRFC framework, allowing one to serialize (i.e. set and enforce the order of execution) multiple tRFC LUWs. As such, qRFC calls use the same or similar framework function modules and tables as tRFC calls, as well as additional framework FMs and tables to track serialization and monitor resources.
Because qRFCs are an extension of tRFCs, I will be assuming the transactional RFCs page has been read before reading this page, and that the tRFC framework FMs and basis tables and their roles are well understood
Once you understand how the tRFC framework functions, most of the information you need to understand qRFCs is contained in the following help pages:
https://help.sap.com/saphelp_nwpi71/helpdata/en/44/fb0b85e1f141dfe10000000a1553f6/frameset.htm - Queued Remote Function Call (qRFC)
As such, this page will be dedicated to emphasizing key concepts and connecting various examples of qRFC scenarios to the transactions, screens, traces, and records you would find in an ABAP AS system.
qRFCs are classified by the direction in which they're processed. There are two classifications, Outbound and Inbound.
To call an Outbound qRFC, the syntax is the same, however, the outbound queue name has to be defined first by calling
CALL FUNCTION 'TRFC_SET_QUEUE_NAME'
EXPORTING QNAME = <queue_name>
CALL FUNCTION <func_name> IN BACKGROUND TASK
[AS SEPARATE UNIT]
To Call an Inbound qRFC, the inbound queue name must be set by first calling
CALL FUNCTION 'TRFC_SET_QIN_PROPERTIES'
QOUT_NAME = <queue_out_name>
QIN_NAME = <queue_in_name>
CALL FUNCTION <func_name> IN BACKGROUND TASK
[AS SEPARATE UNIT]
(Note that the inbound qRFC is first placed in an outbound queue prior to being transferred to the destination; this is why the parameter
QOUT_NAME is available here as well. If no outbound queue name is specified,
QIN_NAME is also used as the outbound queue name.)
qRFC calls, in addition to sharing the same properties as tRFC calls, are assigned to queues using the
qRFC LUWs share the same properties as tRFC LUWs, with the following exceptions: They...
- Are guaranteed to be executed in a predictable order; i.e. Are serialized based on client, queue names, destination, and time stamp.
- Will be prevented from executing if a predecessor LUW encounters an error.
Serialization of Outbound qRFC LUWs:
In addition to the FMs and tables inherited from the tRFC framework:
The following Function Modules are a part of the outbound qRFC framework:
QDEST_RUN (SAPLQOWK) - Called by the qRFC client step to activate the Outbound Scheduler (aka Send Scheduler) if not already active.
QDEST_RUN_DESTINATION (SAPLQOWK) - Called by the Outbound Scheduler to activate the scheduler for a specific destination (the Destination Scheduler). The destination scheduler is responsible for determining the execution order of LUW registered to that destination.
TRFC_QOUT_SEND (SAPLORFC) - Called by the Destination Scheduler. Replaces ARFC_RUN_NOWAIT. it is called to start LUW execution for a queue with no dependencies (i.e. the LUW is next in the queue to be executed).
The following tables are a part of the outbound qRFC framework:
- QSENDDEST - Contains the status of the Outbound Scheduler as well as the Destination Scheduler for each registered outbound destination.
- TRFCQOUT - Analogous to ARFCSSTATE, it records the queue associated with each FM call as well as the timestamp the LUW was registered.
- QIWKTAB - Analogous to QSENDDEST but for registered inbound queues.
There are two main types of outbound schedulers. Each system has 1 system-wide Outbound Scheduler (%QSEND_SCHEDULER, sometimes referred to as the Send Scheduler), and as many Destination Schedulers as there are registered destinations in SMQS.
The state of these schedulers is tracked via the QSENDDEST table.
SMQS and QSENDDEST:
The "Scheduler Information" section in SMQS shows the status of the system-wide Outbound Scheduler. While the table below shows the status of each Destination Scheduler.
The Outbound Scheduler (%QSEND_SCHEDULER) is "activated" (i.e. an ABAP session for that scheduler is created) when QDEST_SEND is called.
A Destination Scheduler (e.g. NONE or S4C from above) is "activated" when QDEST_RUN_DESTINATION is called.
The "Host ID" field tells you on which host that particular scheduler is running (or, if the state is INACTIVE, ran last).
Each scheduler should correspond to at most 1 ABAP session. If the state of a scheduler is INACTIVE, then there should be 0 ABAP sessions acting as that scheduler.
When the schedulers are not INACTIVE they should be able to be seen in SM04. For example (in no particular order):
- The session with QDEST_RUN_DESTINATION is the destination scheduler under which the LUW is being executed
- The session with Z_CPI_WORK_WAIT is the session which is actually executing the function modules registered in the LUW (ZCPI_WORK_WAIT is the first FM in that LUW).
If the destination is another system, you will not see this session next to the schedulers in SM04 of the sending system.
- The session with TRFC_QOUT_SEND is the framework task which calls RFC_PING, ARFC_DEST_SHIP, and ARFC_DEST_CONFIRM in order to actually execute the LUW
- And (unfortunately) the Outbound/Send Scheduler does not show QSEND_DEST in the "Application Info.", but "WI=CLI(...)" above is indeed the session of the Outbound Scheduler.
- The call order is illustrated per the red arrows, which will be demonstrated in the next section.
1 Call - 1 queue - 1 LUW
When called via tRFC, there were three recorded generated, when called via qRFC, five records are generated
As with the STAD records from the tRFC tasks, the total response time of qRFC calls is misleading. While all four tasks have a total response time of ~40 seconds, most of this is task #2, #3, & #4 rolled out waiting for task #5 to finish.
When performance issues occur inside FMs called via the qRFC framework, a proportional increase in roll wait time is expected. Suppose our qRFC server task has a response time of 1 second and makes about 1 second worth of database requests. Consider the following values:
|Task||DB time||Roll Wait time|
Performance problem occurs
and DB time doubles
|new DB time||new Roll Wait time|
This leads to misunderstandings when examining the RFC response time in the Workload Monitor (ST03) of systems which make many tRFC/qRFC calls. This is because the aggregation of this workload data somewhat conceals the actual problem of worsening DB time. Comments often heard are similar to "most of the increase in response time seems to be roll wait time", which is simply a side effect of the tRFC/qRFC framework.
(Note that these times & distributions of time vary depending on the amount of parallel qRFC activity in the system.)
Additionally, note the RFC Server & Client sub records when considering the timeline below.
The timeline was constructed from the ST05 trace
While the above figure is quite busy, the main points are as follows:
ARFCRSTATEare used for qRFC calls in the same way as tRFC calls.
- The LUW is executed using the same framework FMs as in a tRFC LUW.
TRFCQOUTis updated in parallel to
- The SS and DS periodically check the
TRFCQOUTtable for newly registered LUWs since the SS/DS was started (this will be demonstrated later). This ensures only one active instance of the SS and one active instance per destination of the DS is required at any time.
2 Calls - 1 queue - 2 LUWs
Considering the SS, DS, and QO tasks are periodically checking for newly registered LUWs while inactive, what happens when a second LUW containing FM calls in the same queue are registered while the SS, DS, and QO tasks are not inactive?
In this case, there are 6 STAD records created:
(middle click/open in new tab for convenience)
- qRFC Client
- Send Scheduler (SS)
- Destination Scheduler (DS)
- Queue Out (QO)
- qRFC Server1
- qRFC Server2
Notice how the second server task doesn't start until the first one finishes. Also note the RFC sub records, it's the already running QO task that checks and executes the LUW that was registered second (as opposed to the DS starting a new QO task).
Note that the calls to
ARFC_DEST_CONFIRM have been consolidated into a single graphic in this timeline.
Inbound qRFCs are a further extension built on outbound qRFCs.
When an inbound qRFC LUW is created, it is first registered as an outbound LUW in the sending system via the ARFCSSTATE, ARFCSDATA, and TRFCQOUT tables.
Then, using the outbound qRFC framework, the LUW is transferred to the destination system via a call to ARFC_DEST_SHIP, where the LUW is saved to the TRFCQSTATE, TRFCQDATA, and TRFCQIN tables (which determine the queues and serialization).
The inbound scheduler is then activated (if not already active) and the LUW is executed via TRFC_QIN_DEST_SHIP.
In addition to tRFC and outbound qRFC tables and function modules, the inbound qRFC framework uses the following function modules:
- QIWK_RUN (SAPLQIWK) - Analogous to QDEST_RUN; called by ARFC_DEST_SHIP in the receiving/inbound system to activate the system-wide inbound scheduler.
- TRFC_QIN_ACTIVATE (SAPLIRFC) - Analogous to TRFC_QOUT_SEND. Called by the system-wide inbound scheduler to activate a queue scheduler for a specific queue (or a collection of queues as determined by the inclusion of a wildcard when registering queues in SMQR)
- TRFC_QIN_DEST_SHIP (SAPLERFC) - Analogous to ARFC_DEST_SHIP. It's inside this ABAP session that the inbound qRFC LUW is actually executed.
And the following tables:
- TRFCQSTATE - Analogous to ARFCSSTATE. Stores the functions module names of each LUW.
- TRFCQDATA - Analogous to ARFCSDATA. Store the data required to execute each function module (e.g. import parameters).
- TRFCQIN - Analogous to TRFCQOUT. Stores the queuing information for each LUW
- QIWKTAB - Analogous to QSENDDEST. However, there is only 1 inbound scheduler for the whole system
There is only one system-wide inbound scheduler in a system.
There is no need for destination schedulers for inbound LUWs as once an LUW is registered in the TRFCQ* tables it is already "in the destination system" in which is will be executed. All that's left is to execute the inbound LUWs in the correct order.
(It is possible to define a "destination with logon data" when registering queue names in SMQR in order to restrict execution to specific application servers or under a different user and/or client.)
The state of the system-wide scheduler, and the registered queue names, is stored in QIWKTAB.
SMQR and QIWKTAB:
1 Call - 1 Queue - 1 LUW
The outbound qRFC framework is utilized by the sending system, and the inbound qRFC framework is utilized by the receiving system.