为什么某些 RFC 受到最大限制 GUI 会话的数量?

问题描述

通过 RFC 多次调用函数 ME_INFORECORD_MAINTAIN_MULTI 失败,并显示“已达到最大 GUI 会话数”的简短转储,但其他函数在以相同方式调用时似乎不受会话限制的限制。

我可以对此函数进行的并行调用次数取决于我当前打开的 GUI 会话(SAP GUI 窗口)的数量。

例如,以下代码在 5 次调用后失败(我在发生转储的行的开头添加了 >>>):

FORM CALL_BAPI_INFORECORD.
lv_taskname = |PIR-{ lv_sentjobs WIDTH = 3 ALIGN = RIGHT PAD = '0' }|.
DATA: lv_retry TYPE ABAP_BOOL.
lv_retry = ABAP_TRUE.

WHILE lv_retry = ABAP_TRUE.
  lv_retry = ABAP_FALSE.
  CALL FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
    STARTING NEW TASK lv_taskname
    DESTINATION IN GROUP DEFAULT
    PERFORMING RETURN_BAPI_INFORECORD ON END OF TASK
    [...]
  EXCEPTIONS
    system_failure        = 1 MESSAGE lv_exceptionmsg
    communication_failure = 2 MESSAGE lv_exceptionmsg
    resource_failure      = 3
CASE sy-subrc.
  WHEN 0.
    lv_sentjobs = lv_sentjobs + 1.
  WHEN 1 OR 2.
    MESSAGE lv_exceptionmsg TYPE 'I'.
    WRITE: / lv_taskname,':',lv_exceptionmsg.
  WHEN 3.
    WAIT FOR ASYNCHRONOUS TASKS UNTIL lv_recvjobs = lv_sentjobs UP TO 300 SECONDS.
    lv_retry = ABAP_TRUE.
  WHEN OTHERS.
    MESSAGE 'Unkown error.' TYPE 'I'.
ENDCASE.
ENDWHILE.
ENDFORM.

FORM RETURN_BAPI_INFORECORD USING TASKNAME.
  DATA INFO LIKE RFCSI.
>>> RECEIVE RESULTS FROM FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
    IMPORTING
      RFCSI_EXPORT = INFO
      RETURN = GT_ME_INFORECORD_RETURN.
ENDFORM.

...但以下代码在 10 个并行调用时运行良好:

FORM CALL_BAPI_MATERIAL.
lv_taskname = |MAT-{ lv_sentjobs WIDTH = 3 ALIGN = RIGHT PAD = '0' }|.
DATA: lv_retry TYPE ABAP_BOOL.
lv_retry = ABAP_TRUE.

WHILE lv_retry = ABAP_TRUE.
lv_retry = ABAP_FALSE.
  CALL FUNCTION 'BAPI_MATERIAL_SAVEREPLICA'
    STARTING NEW TASK lv_taskname
    DESTINATION IN GROUP DEFAULT
    PERFORMING RETURN_BAPI_MATERIAL ON END OF TASK
    [...]
  EXCEPTIONS
    system_failure        = 1 MESSAGE lv_exceptionmsg
    communication_failure = 2 MESSAGE lv_exceptionmsg
    resource_failure      = 3.

CASE sy-subrc.
  WHEN 0.
    lv_sentjobs = lv_sentjobs + 1.
  WHEN 1 OR 2.
    MESSAGE lv_exceptionmsg TYPE 'I'.
    WRITE: / lv_taskname,lv_exceptionmsg.
  WHEN 3.
    WAIT FOR ASYNCHRONOUS TASKS UNTIL lv_recvjobs = lv_sentjobs UP TO 300 SECONDS.
    lv_retry = ABAP_TRUE.
  WHEN OTHERS.
    MESSAGE 'Unknown error.' TYPE 'I'.
ENDCASE.
ENDWHILE.
ENDFORM.

FORM RETURN_BAPI_MATERIAL USING TASKNAME.
  DATA INFO LIKE RFCSI.
  RECEIVE RESULTS FROM FUNCTION 'BAPI_MATERIAL_SAVEREPLICA'
    IMPORTING
      RFCSI_EXPORT = INFO
      RETURNMESSAGES = GT_BAPI_SAVEREPLICA_RETURN.
ENDFORM.

这是发生转储时的堆栈。

enter image description here

为什么函数 ME_INFORECORD_MAINTAIN_MULTI 受到 GUI 会话的限制以及如何绕过它?

解决方法

你确定你出错了

“已达到最大 GUI 会话数”

由于函数调用?

CALL FUNCTION 'BAPI_MATERIAL_SAVEREPLICA'
    STARTING NEW TASK lv_taskname
    DESTINATION IN GROUP DEFAULT
    PERFORMING RETURN_BAPI_MATERIAL ON END OF TASK

您是否在调用函数语句中包含了异常?

    exceptions   resource_failure =  1
                 others         = 2.

当组上没有更多免费资源时,您将收到“resource_failure”异常。 根据您的描述,我预计会出现资源故障错误

检查您正在使用的服务器组的 Rz12 中的设置。 “启动新任务”(通过 rfc)的能力检查这些参数设置。 因此,如果服务器“忙”,则呼叫失败。 enter image description here

这是一个可用于测试并行代码行为的基本 shell 程序。

REPORT ZPARA.
data t type i.

parameters:
            cnt    type i default 10000000,packets type i default 10,para as checkbox default 'X',waittime type i default 1,rfcgroup like rzllitab-classname .


data  total type f.
data  splits type i.
data  mod type i.
data packetsize type i.
data: first type i.
data: last type i.
data: this_last type i.
data: this_split type i.
data: ret_splits type i.
data: act_splits type i.
data: taskname type num8 value 0.
data: begin of task occurs 0,taskname type num8,uzeit like sy-uzeit,wpinfo TYPE WPINFO,end of task.

data max_pbt_wps type i.
data free_pbt_wps type i.
 
start-of-selection.

    PERFORM classic_version.


form classic_version.
**** TO USE THIS CODE,* create a parallel(rfc) server group in RZ12.
* create the function decribed below 
**************************************************
* set run time res low,so measurement in milli not microsecs.
* we are measure BIG runs

refresh task.

set run time clock resolution low.
get run time field t.
total = 0.

check cnt > 0.

if packets = 0.
   packets = 5.
endif.

* splits calculated based on packet size

splits = packets.
PACKETSIZE = cnt div PACKETS.

* is parallel mode selected
if para = 'X'.

* parallel processing MUST be initialized first.

  call function 'SPBT_INITIALIZE'
   exporting
      group_name                           = rfcgroup
    importing
      max_pbt_wps                          = max_pbt_wps
      free_pbt_wps                         = free_pbt_wps
    exceptions
      invalid_group_name                   = 1
      internal_error                       = 2
      pbt_env_already_initialized          = 3
      currently_no_resources_avail         = 4
      no_pbt_resources_found               = 5
      cant_init_different_pbt_groups       = 6
      others                               = 7
            .
  if sy-subrc <> 0.
* if our group failed or the available processes was 0,* we would exit cleanly here.
* for the demo,just bomb out.

  endif.


   last = 0.
   ret_splits = 0.
  act_splits = 0.

* so for each split
  do splits times.

* make a jobname
    taskname    = taskname + 1.

* work out which chunk we are processing
* ie were are we up to ??
    first       = last + 1.
    this_last   = first + packetsize - 1.

* for info purposes record which split
    this_split = sy-index.

* just in case we have the last split,* calculated adjust target end,if this_last > cnt.
      this_last = cnt.
    endif.

* try a dispatch this split.
* this is where more logic is needed.
* here we set a max of a hundred tries to dispatch
* something. IN VERY LARGE jobs,* a commit work and a more intelligent wait
* might be appropriate.
* we at least wait,1 then 2 then 3... secs etc
* until we get a look in.
   do 100 times.


* inside a parallel ( new ) task
* do a chunk of work.
* NO importing parameters here. The result is returned
* in the receiving function.
* SPECIAL,extra,exceptions are available to control
* success or otherwise of the dispatch.
    write: / 'Split ',this_split,'dispatch at',sy-uzeit.

    call function 'Z_CHUNK' starting new task taskname
        destination in group rfcgroup
        performing finished on end of task
       exporting

        from_int       = first
        to_int         = this_last

      exceptions
        resource_failure =  1
        others         = 2.

     if sy-subrc = 0.
*    dispatch ok,record the fact and march on...
        act_splits = act_splits + 1.
        last =  first + PACKETSIZE - 1.
        exit. " the retry until dispatched loop.
     else.
      write: 'No resource free'.
      write: / 'Split ','Waits ',waittime,'secs at',sy-uzeit.
* wait x seconds,each attempt waits successlively longer
      wait up to waittime seconds.

     endif.

   enddo.

* Actual failure to dispatch is not captured in this version
* your code should consider this issue.

  enddo.

*** THE BIG ROUNDUP
* we wait here until ALL splits are returned.
* we do that by waiting until a return counter
* equals the numbers of dispatches.
* this wait does not wait indefinitely if a dispatch above
* fails,since another continue point is NO oustanding
* async tasks.
***
  wait until ret_splits >= act_splits.

else.

  call function 'Z_CHUNK'
       exporting
            from_int = 1
            to_int   = cnt
       importing
            tot      = total.




endif.

get run time field t.
t = t / 1000.
loop at task.

  write: / 'Received task',task-taskname,' at ',task-uzeit,' in WP:',task-WPINFO-WP_INDEX.

endloop.

write: / 'Parallel',para.
write: / 'Time ms ',t left-justified.
write: / 'Splits  ',splits left-justified.
write: / 'Total   ',total left-justified.

endform.

*---------------------------------------------------------------------*
*       FORM finished                                                 *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  TASKNAME                                                      *
*---------------------------------------------------------------------*
form finished using taskname.
data: ls_wpinfo type WPINFO.
data  l_tot type f.


  receive results from function 'Z_CHUNK'
     importing
        tot = l_tot
        wp_index = LS_WPINFO-WP_INDEX.

* when receiving a task back,we get out result
* and record that the task returned,by uping a counter.



  task-taskname =  taskname.
  task-uzeit = sy-uzeit.
  task-WPINFO = LS_WPINFO.
  append task.

  total = total + l_tot.

  ret_splits = ret_splits + 1.

endform.



*****
* Create this function to test.
FUNCTION Z_CHUNK
  IMPORTING
    VALUE(FROM_INT) TYPE I
    VALUE(TO_INT) TYPE I
  EXPORTING
    VALUE(TOT) TYPE F
    VALUE(WP_INDEX) TYPE WPINFO-WP_INDEX.




data l_i type i.

tot = 0.

check to_int > from_int.

l_i = from_int.

while l_i <= to_int.
   tot = tot + l_i.
   l_i = l_i + 1.
endwhile.

CALL FUNCTION 'TH_GET_OWN_WP_NO'
 IMPORTING
   WP_INDEX       = WP_INDEX
          .

ENDFUNCTION.

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...