RFC (Remote Function Call) — протокол обмена данными между системами (подробно о SAP RFC написано в курсе BC415). RFC применяются для интеграции SAP и не SAP систем, обработки данных в новой сессии, параллельной обработки данных и т.п.
Классификация RFC
- Синхронный RFC или sRFC. Определяется с помощью дополнения DESTINATION. При вызове sRFC рабочий процесс приостанавливает свою работу пока вызываемый sRFC модуль не завершит свою работу. Вызов sRFC выполняется в отдельном DB LUW. При вызове sRFC в основном процессе происходит неявный COMMIT.
- Асинхронные RFC – определяются с помощью дополнения STARTING NEW TASK. К ним относятся асинхронные (aRFC) и параллельные (pRFC) RFC вызовы. При асинхронном вызове, вызываемый модуль запускается в новом процессе и работает параллельно с основным рабочим процессом. Результат выполнения ФМ можно получить в функции обратной связи. Вызовы aRFC и pRFC выполняются в отдельных DB LUW.
- Фоновые RFC – определяются с помощью дополнения IN BACKGROUND. К ним относятся транзакционные (tRFC), очередные (qRFC) и фоновые (bgRFC) RFC вызовы. ФМ работают независимо от основного процесса и начинают выполнение после команды COMMIT WORK. На все фоновые RFC создается один DB LUW. Результат фонового RFC нельзя передать в основной процесс.
Вызывать по RFC можно любой функциональный модуль, который объявлен как «дистанционный».
Целевая система
Целевая система определяется с помощью DESTINATION dest, где dest — название RFC соединения. Для настройки RFC соединений используется транзакция SM59. Если в качестве dest передать пустую строку, то функция будет выполнена локально. В качестве dest можно передать ‘NONE’ или ‘BACK’.
- DESTINATION ‘NONE’ — вызывает запуск функционального модуля в отдельном сеансе пользователя на том же сервере приложений, что и вызывающая программа.
- DESTINATION ‘BACK’ — вызывает запуск функционального модуля в системе, из которой был функциональный модуль. Используется для этого обратного вызова в синхронных RFC.
Исключения
В RFC функциях, помимо запрограммированных исключений, можно обработать системные исключения:
- COMMUNICATION_FAILURE – возникает когда связь с сервером не установлена либо когда соединение было прервано.
- SYSTEM_FAILURE – возникает когда на удаленной системе возникла ошибка.
Примечание
Системные исключения COMMUNICATION_FAILURE и SYSTEM_FAILURE можно объявить с MESSAGE msg. Тогда, при наступлении исключения в msg вернется любое сообщение из целевой системы.
Синхронный RFC (sRFC)
При синхронном вызове RFC, рабочий процесс приостанавливает свою работу пока вызываемый модуль не завершит свою работу. Вызов выполняется в отдельном DB LUW. При вызове sRFC в основном процессе происходит неявный COMMIT. Поэтому вызовы sRFC не должны находиться между OpenSQL операторами, обновляющие БД.
При повторном вызове sRFC, глобальные данные группы функций вызываемого ФМ будут доступны до тех пор, пока не будет закрыто указанное соединение.
Если в sRFC вызывает CALL SCREEN, CALL TRANSACTION или отображение списка, то вызываемые экраны будут отображены в программе запустившей sRFC, но только если в настройках соединения разрешен диалоговый удаленный доступ, в противном случае возникнет исключение SYSTEM_FAILURE.
Пример ниже демонстрирует синхронный вызов RFC и обработку возможных видов исключений.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
REPORT z_test_rfc. START-OF-SELECTION. PERFORM main. FORM main. PERFORM call_rfc USING 1 ''. " Локальный вызов PERFORM call_rfc USING 1 'NONE'. " Вызов в новой сессии PERFORM call_rfc USING 0 'NONE'. " Ожидаем определенное исключение PERFORM call_rfc USING 1 'UNKNOWN'. " RFC не существует PERFORM call_rfc USING -1 'NONE'. " Ожидаем ошибку на удаленной системе ENDFORM. FORM call_rfc USING iv_foo TYPE i iv_rfc TYPE rfcdest. DATA lv_msg TYPE c LENGTH 80. DATA lv_foo TYPE i. DATA lv_bar TYPE i. CALL FUNCTION 'Z_TEST_RFC' DESTINATION iv_rfc EXPORTING iv_foo = iv_foo IMPORTING ev_bar = lv_bar EXCEPTIONS communication_failure = 1 MESSAGE lv_msg system_failure = 2 MESSAGE lv_msg wrong_input = 3. CASE sy-subrc. WHEN 0. WRITE: / 'Успешно выполнено.'. WHEN 1. WRITE: / 'Исключение COMMUNICATION_FAILURE:', lv_msg. WHEN 2. WRITE: / 'Исключение SYSTEM_FAILURE:', lv_msg. WHEN 3. WRITE: / 'Исключение функционального модуля WRONG_INPUT.'. ENDCASE. ENDFORM. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
FUNCTION z_test_rfc. *"---------------------------------------------------------------------- *"*"Локальный интерфейс: *" IMPORTING *" VALUE(IV_FOO) TYPE I *" EXPORTING *" VALUE(EV_BAR) TYPE I *" EXCEPTIONS *" WRONG_INPUT *"---------------------------------------------------------------------- IF iv_foo GT 0. ev_bar = 1. ENDIF. IF iv_foo EQ 0. RAISE wrong_input. ENDIF. IF iv_foo LT 0. MESSAGE e126(00). " Введите только положительные значения ENDIF. ENDFUNCTION. |
Результат
Аинхронный RFC (aRFC)
При асинхронном вызове RFC, вызываемый модуль запускается в новом процессе и работает параллельно с основным рабочим процессом. Вызов выполняется в отдельном DB LUW. Для запуска ФМ в асинхронном режиме необходимо вызвать ФМ с ключевыми словами STARTING NEW TASK <имя_задачи>.
Результат работы aRFC можно получить в функции обратного вызова, которая указывается с помощью ключевого слова PERFORMING <имя_процедуры> ON END OF TASK. При вызове aRFC из метода класса, функцией обратной связи может быть публичный метод, который определяется с помощью ключевого слова CALLING <имя_метода> ON END OF TASK. Указанные процедура или метод должны иметь один USING или IMPORTING параметр p_task типа clike, в который будет передаваться название задачи. Для получения данных из aRFC, внутри данной процедуры, используется обязательная команда RECEIVE RESULTS FROM FUNCTION <имя_функционального_модуля> c параметрами IMPORTING, TABLES, EXCEPTIONS которые будут переданы из aRFC.
Для ожидания выполнения aRFC вызовов используется команда WAIT UNTIL <условие>. Если условие выполняется, программа продолжит выполнение, если нет, то процесс будет ждать окончания выполнения следующего aRFC, пока условие не будет выполнено или не будут выполнены все aRFC вызовы.
В aRFC доступно системное исключение RESOURCE_FAILURE. Оно возникает если на сервере нет свободных ресурсов.
Пример ниже демонстрирует вызов нескольких aRFC и возврат результата в основной процесс. Функциональный модуль Z_TEST_RFC взят из примера sRFC.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
REPORT z_test_rfc. TYPES: BEGIN OF gts_task, task TYPE c LENGTH 5, foo TYPE c LENGTH 5, bar TYPE c LENGTH 5, subrc TYPE c LENGTH 5, message TYPE text80, END OF gts_task. DATA gv_tasks TYPE i. DATA gt_tasks TYPE TABLE OF gts_task. FIELD-SYMBOLS <gs_tasks> TYPE gts_task. START-OF-SELECTION. PERFORM main. FORM main. CLEAR gv_tasks. PERFORM call_rfc USING 1 ''. " Локальный вызов PERFORM call_rfc USING 1 'NONE'. " Вызов в новой сессии PERFORM call_rfc USING 0 'NONE'. " Ожидаем определенное исключение PERFORM call_rfc USING 1 'UNKNOWN'. " RFC не существует PERFORM call_rfc USING -1 'NONE'. " Ожидаем ошибку на удаленной системе WAIT UNTIL gv_tasks EQ 0. WRITE: / `Task `, `Foo `, `Bar `, `Subrc`, `Message`. LOOP AT gt_tasks ASSIGNING <gs_tasks>. WRITE: / <gs_tasks>-task, <gs_tasks>-foo, <gs_tasks>-bar, <gs_tasks>-subrc, <gs_tasks>-message. ENDLOOP. WRITE / 'Все задачи выполнены.'. ENDFORM. FORM call_rfc USING iv_foo TYPE i iv_rfc TYPE rfcdest. DATA lv_msg TYPE c LENGTH 80. APPEND INITIAL LINE TO gt_tasks ASSIGNING <gs_tasks>. <gs_tasks>-task = lines( gt_tasks ). <gs_tasks>-foo = iv_foo. CALL FUNCTION 'Z_TEST_RFC' DESTINATION iv_rfc STARTING NEW TASK <gs_tasks>-task PERFORMING callback ON END OF TASK EXPORTING iv_foo = iv_foo EXCEPTIONS communication_failure = 1 MESSAGE lv_msg system_failure = 2 MESSAGE lv_msg. IF sy-subrc EQ 0. lv_msg = 'Задача запущена'. ENDIF. <gs_tasks>-subrc = sy-subrc. <gs_tasks>-message = lv_msg. ADD 1 TO gv_tasks. ENDFORM. FORM callback USING p_task TYPE clike. DATA lv_bar TYPE i. DATA lv_msg TYPE c LENGTH 80. READ TABLE gt_tasks ASSIGNING <gs_tasks> WITH KEY task = p_task. CHECK sy-subrc EQ 0. RECEIVE RESULTS FROM FUNCTION 'Z_TEST_RFC' IMPORTING ev_bar = lv_bar EXCEPTIONS system_failure = 1 MESSAGE lv_msg wrong_input = 2. CASE sy-subrc. WHEN 0. lv_msg = 'Задача успешно выполнена.'. WHEN 2. lv_msg = 'Исключение WRONG_INPUT.'. ENDCASE. <gs_tasks>-subrc = sy-subrc. <gs_tasks>-message = lv_msg. <gs_tasks>-bar = lv_bar. SUBTRACT 1 FROM gv_tasks. ENDFORM. |
Результат
Параллельный RFC (pRFC)
В ситуациях, когда требуется распараллелить выполнение пула однотипных операций, вместо aRFC рекомендуется использовать pRFC. Параллельный RFC работает схожим образом с aRFC и вызывается с помощью дополнения DESTINATION IN GROUP <имя_группы>. Группы pRFC настраиваются в RZ12. Если в качестве имени группы указать DEFAULT или SPACE, то вызов будет происходить на любой из определенных групп, в зависимости от их загруженности.
Для определения доступности ресурсов определенной группы можно воспользоваться ФМ SPBT_INITIALIZE.
Для определения сервера, на котором будет выполняться задача pRFC необходимо вызывать ФМ SPBT_GET_PP_DESTINATION сразу же после запуска pRFC.
Чтобы исключить конкретный сервер из дальнейшего использования для задач параллельной обработки (например, при исключении COMMUNICATION_FAILURE), необходимо использовать ФМ SPBT_DO_NOT_USE_SERVER.
Пример ниже демонстрирует параллельную обработку с учетом доступности ресурсов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
REPORT z_test_rfc. TYPES: BEGIN OF gts_task, task TYPE c LENGTH 5, input TYPE i, result TYPE i, END OF gts_task. DATA gv_tasks TYPE i. DATA gt_tasks TYPE TABLE OF gts_task. START-OF-SELECTION. PERFORM main. FORM main. DATA lv_total TYPE i. DATA lv_free TYPE i. FIELD-SYMBOLS <ls_tasks> TYPE gts_task. CALL FUNCTION 'SPBT_INITIALIZE' EXPORTING group_name = space IMPORTING max_pbt_wps = lv_total " Число рабочих процессов в группе free_pbt_wps = lv_free " Число доступных процессов в группе EXCEPTIONS invalid_group_name = 1 " Неизвестная группа (см. RZ12) internal_error = 2 " Внутренняя ошибка SAP (см. SM21) pbt_env_already_initialized = 3 " Группа уже инициализирована currently_no_resources_avail = 4 " Нет доступных ресурсов no_pbt_resources_found = 5 " В группе нет серверов с процессами > 2 cant_init_different_pbt_groups = 6 " Другая группа уже была инициализирована ранее OTHERS = 7. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. " Запуск пула однотипных задач DO 10 TIMES. PERFORM proc USING sy-index. ENDDO. WAIT UNTIL gv_tasks EQ 0. WRITE: / `Task`, ` Input`, ` Result`. LOOP AT gt_tasks ASSIGNING <ls_tasks>. WRITE: / <ls_tasks>-task, <ls_tasks>-input, <ls_tasks>-result. ENDLOOP. WRITE / 'Все задачи выполнены.'. ENDFORM. FORM proc USING VALUE(iv_input) TYPE i. DATA lv_tasks_run TYPE i. DATA lv_rfcdest TYPE rfcsi-rfcdest. DATA lv_msg TYPE c LENGTH 80. FIELD-SYMBOLS <ls_tasks> TYPE gts_task. APPEND INITIAL LINE TO gt_tasks ASSIGNING <ls_tasks>. <ls_tasks>-task = lines( gt_tasks ). <ls_tasks>-input = iv_input. lv_tasks_run = gv_tasks. DO. CALL FUNCTION 'Z_TEST_RFC' STARTING NEW TASK <ls_tasks>-task DESTINATION IN GROUP DEFAULT PERFORMING callback ON END OF TASK EXPORTING iv_input = iv_input EXCEPTIONS communication_failure = 1 MESSAGE lv_msg system_failure = 2 MESSAGE lv_msg resource_failure = 3. CASE sy-subrc. WHEN 0. " Задача успешно запущена ADD 1 TO gv_tasks. EXIT. WHEN 1 OR 2. " Получаем имя сервера CALL FUNCTION 'SPBT_GET_PP_DESTINATION' IMPORTING rfcdest = lv_rfcdest. " И исключаем его из параллельной обработки CALL FUNCTION 'SPBT_DO_NOT_USE_SERVER' EXPORTING server_name = lv_rfcdest. ENDCASE. " Ждем пока не осводятся ресурсы WAIT UNTIL gv_tasks LT lv_tasks_run UP TO 1 SECONDS. ENDDO. ENDFORM. FORM callback USING p_task TYPE clike. FIELD-SYMBOLS <ls_tasks> TYPE gts_task. READ TABLE gt_tasks ASSIGNING <ls_tasks> WITH KEY task = p_task. CHECK sy-subrc EQ 0. RECEIVE RESULTS FROM FUNCTION 'Z_TEST_RFC' IMPORTING ev_result = <ls_tasks>-result. SUBTRACT 1 FROM gv_tasks. ENDFORM. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
FUNCTION z_test_rfc. *"---------------------------------------------------------------------- *"*"Локальный интерфейс: *" IMPORTING *" VALUE(IV_INPUT) TYPE I *" EXPORTING *" VALUE(EV_RESULT) TYPE I *"---------------------------------------------------------------------- DATA lv_sec TYPE i. CALL FUNCTION 'RANDOM_I4' EXPORTING rnd_min = 3 rnd_max = 5 IMPORTING rnd_value = lv_sec. WAIT UP TO lv_sec SECONDS. " Имитация работы длительной операции ev_result = iv_input * iv_input. ENDFUNCTION. |
Результат работы pRFC с учетом доступности ресурсов
Примечание
Если в pRFC вы используете алгоритм, требующий отдельной сессии (например пакетный ввод), то полагаться на исключение RESOURCE_FAILURE будет некорректно. Для определения максимального числа доступных процессов можно воспользоваться ФМ TH_USER_INFO.
1 2 3 4 5 6 7 8 9 10 |
DATA lv_act_sessions TYPE i. DATA lv_max_sessions TYPE i. DATA lv_free_sessions TYPE i. CALL FUNCTION 'TH_USER_INFO' IMPORTING act_sessions = lv_act_sessions max_sessions = lv_max_sessions. lv_free_sessions = lv_max_sessions - lv_act_sessions. |
SAP Help на тему параллельной обработки.
Транзакционный RFC (tRFC)
При запуски tRFC основной процесс продолжает работу. Запуск tRFC осуществляется с помощью дополнения IN BACKGROUND TASK. Выполнение tRFC начинается после вызова COMMIT WORK либо после вызова ФМ START_OF_BACKGROUNDTASK. Для всех tRFC создается один DB LUW аналогично модулям обновления, это дает возможным сделать ROLLBACK во всех tRFC если возникнет ошибка хотя бы в одном tRFC. В отличие от aRFC и pRFC, результат tRFC нельзя вернуть в программу через RECEIVE RESULTS FROM FUNCTION.
Использование дополнения AS SEPARATE UNIT функциональный модуль выполняется в отдельном контексте, в котором на глобальные данные группы функций не влияют предыдущие вызовы. Это означает, что при использовании одного и того же DESTINATION для нескольких вызовов tRFC, принадлежащих к одной и той же группе функций, глобальные данные этой группы функций доступны всем последующим tRFC.
Пример запуска tRFC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
REPORT z_test_rfc. START-OF-SELECTION. PERFORM main. FORM main. " Глобальные переменные общие для всех tRFC DO 10 TIMES. CALL FUNCTION 'Z_TEST_RFC' IN BACKGROUND TASK EXPORTING iv_input = sy-index. ENDDO. " Для каждого tRFC свой набор глобальных переменных DO 10 TIMES. CALL FUNCTION 'Z_TEST_RFC' IN BACKGROUND TASK AS SEPARATE UNIT EXPORTING iv_input = sy-index. ENDDO. " Запуск всех tRFC COMMIT WORK. ENDFORM. |
Очередный RFC (qRFC)
Очередный RFC — вариант tRFC, учитывающий порядок вызова модулей. В случае tRFC очередность выполнения модулей может не совпадать с порядком их вызовов. Для установки очередности необходимо перед каждым вызовом qRFC вызвать ФМ TRFC_SET_QUEUE_NAME с указанием имени очереди.
Пример ниже демонстрирует выполнение qRFC в том же порядке, в котором были вызваны модули
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
REPORT z_test_rfc. START-OF-SELECTION. PERFORM main. FORM main. DATA lv_index TYPE i. DATA lv_qname TYPE trfcqout-qname. DO 10 TIMES. lv_index = sy-index. lv_qname = 'Q' && lv_index. CALL FUNCTION 'TRFC_SET_QUEUE_NAME' EXPORTING qname = lv_qname. CALL FUNCTION 'Z_TEST_RFC' IN BACKGROUND TASK EXPORTING iv_input = lv_index. ENDDO. COMMIT WORK. ENDFORM. |
Фоновый RFC (bgRFC)
Фоновый RFC является технологией преемника tRFC и qRFC. SAP настоятельно рекомендует использовать bgRFC вместо tRFC и qRFC. Вызов bgRFC осуществляется с помощью дополнения IN BACKGROUND UNIT <oref>, где oref — ссылка на экземпляр класса, реализующий интерфейс IF_BGRFC_UNIT. Объект содержит всю информацию, требуемую для удаленного вызова функции, включая DESTINATION, тип вызова (tRFC или qRFC), количество очередей. Если один и тот же объект используется для нескольких вызовов, все вызываемые функциональные модули выполняются в одном модуле. И наоборот, несколько объектов этого типа могут использоваться параллельно в одном внутреннем сеансе, что обеспечивает параллельную обработку.
Примеры использования bgRFC можно найти в SAP через журнал использования по интерфейсу IF_BGRFC_UNIT.
Присоединиться к обсуждению...