SAP ABAP程序优化-多线程并行处理

本文介绍了如何在SAP ABAP中通过RFC接口进行远程函数的异步调用来实现程序的并行处理,从而提高执行效率。文中详细讨论了同步与异步调用的区别,并针对异步调用可能遇到的问题,如后台任务冲突、结果差异和服务器组通用性,提出了相应的解决方案。通过实例展示了同步和异步调用的运行时间对比,证明了并行处理的有效性。
摘要由CSDN通过智能技术生成
               

转载请标明出处:http://blog.csdn.net/wanglei880526/article/details/8949754

实际项目实施过程中,我们会遇到程序性能优化的问题,这里介绍一种方法:通过RFC接口进行远程函数的异步调用实现程序的并行处理。

   同步/异步调用函数语法

同步调用:CALL FUNCTION 'AAA' ;

同步调用的实质:程序进行单线程执行。

异步调用:CALL FUNCTION 'AAA' STARTING NEWTASK <taskname> "任务名称

DESTINATION IN GROUP <RFC Serve Group>

                         PERFORMING <subroutine>ON END OF TASK。"子程序

    异步调用的实质:程序进行多线程执行。

一些关于函数异步调用实现程序并行处理的文章,没有介绍如下问题:

⒈ 为了避免相同程序重复运行产生的后台任务相互冲突,需要保证在相同时间段同一程序只被一个用户占用;

⒉ 异步调用获取的最终结果数据与同步调用获取的结果存在差异;

⒊ 固定RFC Server Group如system = 'parallel_generators'无法保证程序在不同服务器中通用性。

问题1分析:从MD01中运行MRP我们可以知道,系统为了避免相同程序并发执行,导致后台任务冲突, MD01在并行模式下是不允许被两个用户同时执行的。如下图



解决方法:通过在程序中利用锁对象来达到程序相同时间段只被同一用户占用的目的。


问题2分析:在LOOP循环中采用异步调用函数的模式,通过SY-SUBRC = 0来判断任务启动成功,当SY-SUBRC <> 0时,则获取先前启动的进程返回的值,但是这样就遇到一个问题:如第N次循环正好分配给程序的进程被占用完,这样本次无法启动一个任务进程,导致本次的原始数据通过函数无法获取目标,从而最终结果出现数据不完整和数值不断变化的现象。

解决方法:牺牲部分性能保证数据的完整。通过RZ12获取服务器的Max. requests in queue 的值,LOOP循环的时候统计启动的启动的进程数是否 = Max. requests inqueue,如果等于则获取先前启动的进程返回的值,然后再重新启动进程,重复此操作。系统分配给每个程序的最大进程数> Max. requests in queue,但是把启动的进程数限制在Max.requests in queue的水平可以保证获取结果的完整性。如下图所示



问题3分析:一般系统直接指定<RFC Serve Group> =' parallel_generators ',如上图的“服务器组”对应的内容,为了保持一般性通过如下逻辑段获取

CALL 'C_SAPGPARAM'  "#EC CI_CCALL                     ID 'NAME'  FIELD 'rdisp/myname'
    ID 'VALUE' FIELD g_applserver.  "
  SELECT SINGLE classname
    FROM rzllitab
    INTO g_classname   "Server Group Name
    WHERE applserver = g_applserver
    AND grouptype = 'S'.   "S:服务器组,空:登陆组


下面通过例子来说明函数异步调用,这里使用函数        

 'MD_STOCK_REQUIREMENTS_LIST_API'获取MD04中的物料+工厂 MRP数据明细。首先我们使用同步调用的方法,然后再使用异步调用的方法,比较二者在同等条件下的执行效率。

(假设需求:从物料工厂表MARC中获取一定的行项目,这里设定为18000条,然后通过调用函数获取物料工厂对应的MRP清单,将物料工厂与获取的对应清单整合输出)

同步调用:(完整程序在程序最后)

select matnr werks

    UP TO 18000 ROWS               "数据条目18000
    INTO CORRESPONDING FIELDS OF TABLE it_marc
    FROM marc
    WHERE matnr IN s_matnr
    AND   werks IN s_werks.
 
  LOOP AT it_marc INTO wa_marc.
    CLEAR it_md.
    CALL FUNCTION  'MD_STOCK_REQUIREMENTS_LIST_API'
      EXPORTING
        MATNR                    = wa_marc-matnr
        WERKS                    = wa_marc-werks
      TABLES
        MDEZX                    = it_md
      EXCEPTIONS
        MATERIAL_PLANT_NOT_FOUND = 1
        PLANT_NOT_FOUND          = 2
        OTHERS                   = 3.
 
    LOOP AT it_md INTO wa_md.
      MOVE-CORRESPONDING wa_md TO wa_output.
      wa_output-matnr = wa_marc-matnr.
      wa_output-werks = wa_marc-werks.
      APPEND wa_output TO it_output.
      CLEAR:wa_output,wa_md.
    ENDLOOP.
    CLEAR wa_marc.
  ENDLOOP.

很显然在同步执行情况下,只有一个进程是执行我们调用的函数,其他的进程处于idle状态。


异步调用:

解决问题1:为了达到当前用户可以独占程序,进入选择界面即锁定程序:

AT SELECTION-SCREEN.
  "锁定程序
  CALL FUNCTION 'ENQUEUE_EZZSOPR0032'
    EXPORTING
      mode_trdir     = 'E'         "锁类型
      name           = 'ZSOPR0032' "锁对象名称
      x_name         = ' '
      _scope         = '2'
      _wait          = ' '
      _collect       = ' '
    EXCEPTIONS
      foreign_lock   = 1
      system_failure = 2
      OTHERS         = 3.
  IF sy-subrc <> 0.
    MESSAGE '对象已被锁定,请稍后执行' TYPE 'E'.
  ENDIF.

解决问题1:当程序异步调用函数的操作结束后,即可接触对程序的锁定:

END OF SELECTION.
  "解除程序的锁定
  CALL FUNCTION 'DEQUEUE_EZZSOPR0032'
    EXPORTING
      mode_trdir = 'E'
      name       = 'ZSOPR0032'
      x_name     = ' '
      _scope     = '3'
      _synchron  = ' '
      _collect   = ' '.

 

解决问题3:获取RFC Serve Group name

*  获取 RFC Serve Group name         Start--*
* 一般系统默认g_classname = 'parallel_generators',但为了通用性按照如下方法获取
  CALL 'C_SAPGPARAM'                                      "#EC CI_CCALL</
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值