
SAP系统跑得慢、月底结账卡死、大批量过账直接把生产机拖垮这些事儿干过企业应用运维的人多少都遇到过。而要想在业务出问题之前把系统的真实承受能力摸清楚压测就是绕不开的一道工序。我在给客户做SAP系统性能评估的时候最常用的工具就是LoadRunner虽然它年纪不小但在SAP这套老牌ERP的压测场景里它依然是不可替代的存在。这篇博文就把我这些年用LoadRunner压测SAP的完整思路、具体操作、以及踩过的坑一次性讲清楚。不管你是刚接手SAP性能测试的测试工程师还是被领导安排“做个压测”却不知从何下手的Basis这篇文章都能给你一条可以直接照着走的路。我会从协议选型、脚本录制、场景设计、监控分析到问题排查把每个环节里真正有用的细节全部摊开来讲。1. 为什么压测SAP是个技术活而LoadRunner是首选1.1 SAP压测到底在测什么先说清楚一个很多人容易搞混的点SAP不是一个普通网站你拿个浏览器录一遍、回放一遍就算压测了那基本是在自欺欺人。SAP ECC或者S/4HANA是典型的三层架构前端是SAP GUI或者Fiori这样的表现层中间是ABAP应用服务器NetWeaver底层还有独立的数据库。用户每一次点击从前端发出DIAG请求经过应用服务器解析成ABAP程序调用再落到数据库执行SQL最后把结果一层层传回来。这条链路如果不完整走一遍压测就毫无意义。所以SAP压测的本质是验证这整套三层架构在特定并发量下的表现。具体要测什么我一般会分三类来看。第一类是对话型操作比如用户登录、查报表、维护主数据这类操作直接决定一线员工的日常体验耗时最长也最容易暴露问题。第二类是批量型任务比如月末结账、MRP运算、大批量过账MIGO这类操作往往是压垮系统的最后一根稻草。第三类是接口型调用比如RFC接口、IDoc报文这类调用在系统集成场景里最容易被忽略一出问题就是上下游连锁故障。压测的核心目标就是要搞清楚系统在什么并发水平下响应时间开始劣化、什么时候崩溃以及瓶颈究竟在应用服务器、数据库还是网络层。只有把这些量化出来后续的容量规划、Basis调优、硬件扩容才有可能的依据。1.2 为什么不是JMeter也不是k6这些年JMeter和k6在互联网圈子里很火动不动就“秒级压测”“百万并发”听起来挺唬人但真拿到SAP场景里两个工具都撑不起场面。JMeter的核心协议是HTTP/HTTPS它压不了SAP GUI。SAP GUI走的是DIAG协议这是SAP私有的、基于RFC的桌面客户端协议JMeter根本识别不了。你硬要压只能退而求其次压Fiori或者SAP Web GUI这种Web端入口但这样一来桌面端用户的真实操作行为就完全覆盖不到。k6就更不用说了它擅长的方向是轻量API验证和云原生场景对SAP这种重量级ERP的协议栈和企业级业务逻辑基本使不上劲。LoadRunner之所以是首选关键在于它提供了SAP GUI协议族可以直接录制和回放SAP GUI上的完整用户操作。从登录、查询到过账、打印每一帧DIAG报文都能被准确捕获和重放。此外LoadRunner也支持Web/HTTP协议来压Fiori支持SAP RFC协议来压RFC接口等于把SAP能暴露出来的每一类入口都覆盖了。再加上它自带的Controller场景调度和Analysis分析报表体系一条链路走完出报告也方便。对于正经的企业级SAP性能验证LoadRunner还是最省心的选择。2. 开工前必须搞懂的协议与架构问题2.1 SAP的多层架构决定了协议选择的逻辑协议选错后面的工作全部白费。这个道理我是在项目里实打实验证过的。有一回我接手一个SAP GUI的压测任务前期准备时没太较真心想反正都是抓包回放用Web协议录一下应该也能跑结果录出来的脚本里全是静态资源请求和一堆看不懂的加密报文稍微一回放就报错根本没法维护。后来才弄明白SAP GUI的请求报文承载的是DIAG协议它跟HTTP完全是两码事。DIAG协议比HTTP底一层它要跟SAP应用服务器的dispatcher进程直接建立连接里面的报文格式包含屏幕流、字段值、菜单动作等专有信息普通HTTP录制工具连解析都做不到。所以在LoadRunner里选择正确的协议类型是第一要务。压经典SAP GUI客户端选SapGUI协议压Fiori这种Web端选Web HTTP协议压NetWeaver上的RFC接口选SAP RFC协议。三类协议对应的录制入口和脚本函数完全不同千万不能混着用。如果没有把握宁可在录制前花点时间查清楚入口类型也不要录完发现协议错了再推倒重来。2.2 SAP GUI协议脚本的核心机制LoadRunner的SapGUI协议录制出来之后脚本的本质是一系列sapgui_打头的函数。比如sapgui_open_connection负责建立到SAP服务器的连接sapgui_open_transaction对应打开事务代码的动作sapgui_set_value负责往指定字段里填值sapgui_submit则模拟了点击回车或者按钮提交的过程。理解这些函数的工作方式对调试脚本非常有帮助。以sapgui_set_value为例它并不是简单地把一个字符串塞进去而是会先在当前屏幕的控件树上找到对应字段的标识再通过DIAG协议把值写入SAP GUI的运行时环境。这就意味着脚本能否回放成功很大程度上取决于LoadRunner对当前屏幕上的控件能不能正确识别。如果SAP GUI版本太新、界面控件结构变了而LoadRunner的补丁没跟上回放时就可能找不到控件、报“对象不存在”的错。这里就牵扯出另一个关键点SAP GUI版本兼容性。我压测环境里用的SAP GUI 810整体还算稳定但这个版本跟LoadRunner版本之间的匹配关系要特别注意。LoadRunner官方对不同SAP GUI版本有明确的兼容矩阵在项目启动前必须对照确认否则录制好的脚本换台机器就回放不了排查起来极其痛苦。2.3 Web型应用怎么录怎么压说完SAP GUI再讲一下Fiori这类Web应用怎么处理。Fiori的操作入口完全基于浏览器走的是OData服务换句话说它本质上是HTTP/HTTPS请求。所以压Fiori不必用SapGUI协议用LoadRunner的Web HTTP协议就能完美覆盖。但是用Web协议压Fiori也有几个比GUI特殊的地方。第一是cookies和token的问题。Fiori在做用户认证、OData请求时session相关的动态信息传递很频繁脚本里必须做好关联correlation否则回放的时候用户登录都过不去。第二是Fiori页面大量使用异步请求脚本录制完后要仔细检查那些并发发出的XHR请求别让LoadRunner把同步和异步的顺序搞混导致业务逻辑出错。第三是Fiori请求里的CSRF token这个几乎每次会话都不一样不关联脚本必挂。我个人从实践中得到的结论是如果你们企业同时有SAP GUI用户和Fiori用户那压测时两类入口都要覆盖绝不能只压一边。因为两端的请求链路不同、对应用服务器的压力也不同只压GUI得出的结论跟真实混合负载场景差得很远。3. 实操从录制到出报告的全流程拆解3.1 录制前准备别急着点Record很多新手拿到LoadRunner之后第一件事就是打开VuGen点Record觉得录完就能跑结果录出来的脚本问题一堆。实际上录制前有几件事必须准备到位。第一SAP GUI环境要跟生产保持一致。客户端版本、UI主题、语言设置都尽量跟真实用户对齐因为这些都会影响控件的识别。我建议统一用SAP GUI 810这个版本在兼容性和稳定性上表现均衡也是我踩坑之后固定下来的基线版本。第二测试账号的权限要足够。压测脚本里往往要执行事务代码、查询主数据、过账如果账号权限不够跑到一半弹个权限错误脚本就断了。还有一点容易被忽略压测结束后系统里会产生大量测试数据账号如果有权限创建物料、生成订单那这些数据要规划好清理方案不能把生产环境或测试环境搞脏。我通常会准备一组专门的压测账号通过SAP的LSMW导入一批测试主数据确保每次压测的数据基础是可重复的。第三要在SAP GUI上开启脚本录制支持。在SAP GUI的选项里找到脚本录制相关的设置确认允许外部工具录制GUI操作。这一步不做LoadRunner连窗口都抓不到。第四也是最重要的一步把要压测的业务场景写清楚。比如“创建采购订单-审批-收货-发票校验”是一条完整链路“月末批量过账”“库存查询和MRP运算”是另外的链路。业务场景清单是整个压测的蓝图脚本只是把蓝图落地的手段。我见过太多人上来就录录完才发现录的不是核心业务白白浪费一整天。3.2 关键环节参数化、关联、事务定义录制完成只是开始脚本真正能用还得过三关参数化、关联、事务定义。参数化解决的是数据多样性的问题。假设有200个虚拟用户同时登录如果每个用户都用同一条物料号去查库存那SAP数据库层的锁竞争就会被严重高估压出来的结果没有任何参考价值。正确的做法是把物料号、订单号、用户名这些字段全部参数化从数据文件里按规则取值。SAP压测里参数化的数据还有一个特殊性要保证唯一性。比如压MIGO过账每笔过账如果都使用同一个凭证编号过一笔就报错一笔。这种情况下参数化数据的量要足够大而且最好能配合SAP侧的测试数据准备逻辑一起做。再说关联。SAP系统的动态信息比普通Web应用多得多最典型的就是session ID。每次登录SAP系统都会分配一个R3 session标识脚本里如果不做关联回放到第二个虚拟用户时就必然冲突。还有各种凭证号、物料凭证、会计凭证号这些每次操作都会生成新值必须从服务器的响应中动态提取再传给下一个请求。LoadRunner里做关联有自动和手动两种方式我建议对关键业务链路手动做关联因为自动关联虽然省事但经常会把不相关的动态值也提取出来反而制造一些莫名其妙的问题。事务定义则是让压测结果可分析的前提。SAP一个完整的业务操作通常由多个屏幕交互组成比如创建一个采购订单可能要经过供应商选择、物料选择、数量填写、保存确认好几个步骤。如果不定义事务光看脚本就是一堆sapgui函数的堆叠根本不知道哪个环节慢。正确做法是用lr_start_transaction和lr_end_transaction把关键业务动作包起来比如把“创建采购订单”定义成一个事务把“保存”定义成另一个事务这样在Analysis报表里就能清楚看到每个环节的响应时间分布。3.3 场景设计与并发模型脚本准备好之后真正的考验在Controller场景设计这一环。SAP压测的场景设计有一个跟Web压测很不一样的地方并发模型要贴近真实的业务占比而不是简单粗暴地让所有虚拟用户做同一件事。拿一个制造企业来举例日常系统里可能有40%的用户在做物料查询20%在做销售订单录入15%在生产订单相关的操作剩下的散布在财务过账、库存管理、报表查询等事务上。压测场景如果不按这个比例建模压出来的结果对生产的指导意义就很有限。我通常的做法是在Controller里创建多个脚本组每个组对应一类业务场景然后用百分比模式分配虚拟用户数确保整体负载结构贴近实际。并发加载策略方面建议采用逐步递增的方式不要一上来就200个虚拟用户齐刷刷同时启动。SAP系统对突发的连接建立非常敏感大量用户同时登录会让dispatcher瞬间过载看起来像是系统扛不住实际只是登录风暴把资源占尽了。我惯用的做法是每30秒增加10个用户让系统逐步进入负载状态同时观察响应时间曲线找到性能拐点出现的精确位置。还有一个在SAP压测里很有用的功能集合点。如果要模拟月末结账时财务人员同时执行批量过账操作可以用lr_rendezvous把虚拟用户集齐到某个业务操作之前然后一起触发。这个操作会在极短时间内在数据库产生大量写入请求最容易暴露出锁冲突和数据库瓶颈。3.4 监控与瓶颈定位压测不只是把负载发出去监控才是真正体现水平的地方。LoadRunner生态里有个叫SiteScope的组件可以采集SAP自身的性能计数器。但我个人经验是SAP的监控不能全指望外部工具要跟SAP内置的监控手段配合起来看。跑压力测试的过程中我会同时打开SAP的事务代码ST03N看工作负载统计用SM50盯工作进程状态用ST05做SQL跟踪看数据库访问路径。这几个事务代码是Basis的“万金油”。ST03N能告诉你每个事务的响应时间、CPU时间、数据库时间各占多少帮你快速定位慢在前端还是在DBSM50能看到当前所有对话工作进程在干什么如果全部显示Running状态而请求队列还在增长说明系统已过载ST05则能揪出那些对某张表全表扫描的SQL语句很多压测暴露出来的性能问题最后都查到是缺索引。LoadRunner的Analysis报表同样重要但要看明白得抓到重点。第一是事务响应时间曲线看它在什么时间点开始急剧上升这个点就是系统的性能拐点。第二是每秒事务数TPS看系统在拐点之后还能不能维持吞吐量。第三是服务器资源利用率SAP应用服务器的CPU、内存、数据库的IO等指标跟LoadRunner的加压曲线放在一起对比就能判断瓶颈到底在哪一层。4. 我踩过的坑与排查实录4.1 高频坑一录制成了HTTP底层脚本这个坑我在前面已经提到过但它是如此常见值得单独拿出来再讲一遍。现象是明明用SAP GUI的SapGUI协议录制脚本里却全都是web_url、web_custom_request这样的HTTP函数。问题一般出在LoadRunner的协议识别上有时候SAP GUI的配置方式会让LoadRunner误判成Web入口或者LoadRunner的SapGUI协议组件没装全。解决方案也不复杂。第一检查LoadRunner安装时有没有勾选SapGUI协议支持少了组件就补装补丁。第二在Recording Options里明确指定录制协议不要让它自动识别。第三启动录制时选择正确的程序类型不要把SAP GUI路径配错。如果这几点都确认无误还是有这个问题就检查一下SAP GUI的版本是不是太老有些老版本的SAP GUI不走标准DIAG通道LoadRunner无法识别只能抓成底层TCP报文。4.2 高频坑二SAP GUI脚本回放失败与版本兼容脚本录制成功回放却失败这个问题在SAP压测里特别典型。最常见的报错是“could not find object”或者“window not found”意思就是LoadRunner在当前的SAP GUI界面里找不到录制时候识别的那个控件。排查这个问题的思路要按顺序来。首先确认回放时SAP GUI版本和录制时一致。SAP GUI 810跟SAP GUI 7.x的控件树结构差别很大LoadRunner识别库不通用混用必然报错。其次检查回放时SAP GUI的启动状态脚本回放需要打开对应的SAP GUI窗口如果窗口没弹出或者弹出后焦点不对控件识别就会失败。第三看脚本里有没有正确处理同步等待。SAP GUI是逐屏幕交互的机制每个屏幕加载都需要时间录制时LoadRunner会自动插入同步点但回放网络的快慢不同同步点不够会直接导致下一个操作发生时上一个屏幕还没加载完。我解这类问题通常会在脚本的关键位置手动加sapgui_wait_sync或者调整同步等待超时时间让脚本等一下再执行下一步操作。别看这个动作小它解决的回放稳定性问题比什么都管用。4.3 高频坑三会话数暴涨与后台作业堆积压测跑到一半突然SAP登录不了了或者整个系统像死了一样这种场景遇到过的人一定不陌生。打开SM50一看所有对话工作进程全部被占用后台还有一堆作业在排队。这个问题的根因有两个一个是并发模型太激进虚拟用户没有设置合理的思考时间脚本一直在高速循环操作超过了真实用户的操作频率另一个是关联没做好脚本循环中间有错误重试的机制失败一遍就重试一遍等于把负载翻了好几倍。针对这个问题我的处理分三路并行。第一路是把脚本里的思考时间调回合理范围用lr_think_time模拟真实用户的阅读和输入节奏不要让脚本变成无人值守的机器人。第二路是检查SAP Basis参数尤其是对话工作进程数量rdisp/max_wprc如果默认是20而压测并发是200个用户那就注定有一大堆请求排队。压测前就要预估好并发用户跟工作进程的比例必要时提前调参。第三路是压测方案里要设计好渐进的加载策略不要一上来就让所有虚拟用户同一秒登录。4.4 问题速查表下面这个表是我整理的问题排查速查表基本覆盖了SAP压测中我遇到过的大多数问题收藏好遇事对照找原因能省下不少时间。常见问题可能原因排查手段解决方案脚本录制后全是HTTP函数协议选择错误/组件缺失检查协议类型和组件安装重装SapGUI协议组件指定录制协议回放找不到控件SAP GUI版本不匹配/同步缺失检查版本兼容矩阵和脚本同步点统一至SAP GUI 810手动加同步等待并发后所有进程占满思考时间过短/并发模型激进查看SM50工作进程状态调整思考时间改用渐进式加载凭证号重复导致事务失败参数化不充分查看脚本参数化范围扩大参数化数据量确保唯一性登录后会话冲突关联未处理session ID检查动态值提取对R3 session等动态值做手动关联后台作业堆积批处理进程配置不足检查rdisp/btc相关参数调整批处理工作进程数事务响应时间陡增数据库SQL性能问题用ST05做SQL跟踪优化SQL补索引压测后系统残留大量测试数据数据清理方案缺失检查测试数据量压测后执行数据清理作业5. 脚本细节与优化技巧补充5.1 事务命名与业务串联压测报告能不能被业务和技术两边看懂往往取决于脚本怎么组织。我见过不少报告里面就一堆Transaction001、Transaction002这样的名字看报告的人一头雾水还得回头去翻脚本。正确的做法是事务命名直接跟业务挂钩比如“ME21N_创建采购订单”、“MIGO_收货过账”、“F-02_记账”看名字就知道压的是什么业务出了问题也知道该找哪个模块的人去问。另外真实的SAP业务往往不是单个事务而是一条链路。比如采购订单要先创建然后审批再收货最后发票校验。这种情况下要在一个Action里把整条链路串起来用参数传递中间产生的单据号。串起来之后才能看到整条链路在并发条件下的表现而不是只看单点。我还会把链路上的每一步单独定义成事务这样既能看整条链路的总体响应时间也能定位到具体哪一步拖了后腿。结合不同模块来说MM模块的压测重点在MIGO过账、MD07相关的库存需求清单查看FICO模块重点在自制凭证录入和月末结账的批量操练SD模块重点在销售订单的创建、发货过账和后端开票。不同模块的操作频率不同在场景里分配虚拟用户时权重也要有区别。5.2 从压测看SAP系统配置的短板压测的意义不只是验证当前系统能不能扛住更重要的是透过现象看本质找到系统配置的短板。我常说一个观点压测报告本身不值钱值钱的是报告里指出的调优方向。SAP系统的性能配置有很多关键参数值得关注。最核心的是对话工作进程数rdisp/max_wprc它决定了同时能处理多少在线用户请求。其次是内存相关的参数SAP的扩展内存和堆内存配置不当压测时会出现buffer换页或者内存不足的错误。数据库层的参数同样重要比如Oracle的SGA、PGA或者HANA的内存池配置都直接影响SQL的执行效率。从压测结果往回推配置短板有个简单的思路如果CPU利用率不高但响应时间已经很长多半是锁竞争或者SQL等待如果CPU打满而数据库等待很低说明应用层计算是瓶颈如果网络时间占比很高那就要检查客户端到服务器的链路。每一条线索都对应不同的调整方向方向对了调优才能生效。5.3 后续扩展从LoadRunner到k6、JMeter的迁移视角虽然我主张压SAP首选LoadRunner但也得承认工具选型要看场景和成本。一些企业不想为压测工具付高昂的License费用或者团队对开源工具更熟悉这类情况下可以做一些分层设计。SAP的Fiori和OData接口用JMeter是完全可行的。JMeter对HTTP协议的支持成熟脚本维护也比较轻量配合它的附属插件还能做一些基础的指标统计。k6则适合做轻量级的接口验证和持续集成场景里的冒烟压测它的脚本风格对开发团队来说很友好。但要注意这类工具替代的只是Web/HTTP层那一部分SAP GUI的DIAG协议压测目前还是没有比LoadRunner更成熟的方案。所以我的建议是把压测体系分成两层GUI全链路压测用LoadRunner保持完整性和准确性API接口层用JMeter搭建持续压测能力两者并行不冲突。我实际在项目里就是这个组合LoadRunner出的是面向生产环境的全量验证报告JMeter日常跑一些Fiori接口的回归验证既保证质量也控制了成本。压测SAP这件事上手容易交付难。难的不是把脚本录出来、把场景跑起来而是你能不能把每一次压测的结果解读成对系统的深刻理解。我这些年最大的体会是LoadRunner也好SAP也好工具终究是辅助真正值钱的是你在一次次压测、一次次排查里积累起来的判断力。下次当你面对一个响应时间飙升的曲线能快速说出瓶颈在哪个环节、该调什么参数你就已经是个合格的SAP性能测试人了。