v2tn-测试鼠 https://www.v2tn.com/channel/700 v2tn一个技术文章汇聚平台,帮助技术人更快掌握互联网动态
一个漏测Bug能让你想到多少? https://www.v2tn.com/content/1685370451022380 <h2><strong>一、背景</strong></h2> <p>漏测Bug是指产品逻辑缺陷在测试过程中没有被发现(尤其是测试环境可以重现的缺陷),上线版本发布后或者在用户使用体验后发现并反馈回来的缺陷。可能造成线上故障或者资损,在对产品测试过程中,自己也难免出现一些Bug的漏测,因此对Bug漏测进行一些思考,并进行总结。</p> <h2><strong>二、原因分析</strong></h2> <p>Bug其实是任何应用产品都会有的一个问题,不是所有的Bug都能被发现,包括资深测试,或多或少的会出现线上缺陷,谁也不能把软件所有的功能操作、运用场景想周全。虽说不能做到完全零缺陷,但是每次发布的产品,我们需要追求缺陷越来越少,产品质量越来越高,减少线上问题的反馈。<br> 为什么会出现缺陷漏测,主要有以下几点:</p> <h3><strong>2.1 &nbsp;需求评审阶段,对业务需求细节理解不明确,设计存在不合理,未深入挖掘隐含拓展需求</strong></h3> <ul> <li> <h4><strong>问题分析</strong></h4> </li> </ul> <p>在实际产品研发过程中,产品需求其实处于一个细化、优化、下钻过程中,在需求PRD文档交互文档输出进行评审时,未能把一些产品细节问题、隐含需求暴露出来,而测试用例的编写是基于PRD、交互文档以及自己对该需求经验理解所涉及测试用例。</p> <ul> <li> <h4><strong>改进措施</strong></h4> </li> </ul> <ol> <li>需求评审前,我们应该先仔细阅读PRD及交互文档,先形成自己对产品的思考,通过脑图的方式列出对产品设计的疑问点,从用户或者从行业角度找出产品设计缺陷点。</li> <li>需求评审会议中,带着列出的疑问点向产品、开发沟通自己对产品的疑惑和质疑点,多提几个为什么?如何实现?数据获取来源?超出预期的数据怎么处理?缓存处理机制如何?数据保存何处?逻辑由前端处理还是后端服务?后端服务逻辑是否跟第三方关联?</li> <li>需求评审完成后,按照一定的功能,将需求拆分成若干大模块,大模块拆分成小功能点,然后考虑功能点的具体实现流程,通过思维导图细分模块功能、从页面、交互、边界处理、接口逻辑、环境配置等维度进行梳理需求,尽可能挖掘隐含可拓展需求点,然后进行一次测试组内需求评审和技术复盘,让协作成员一起补充隐含需求,使得产品设计缺陷尽早且最大化地暴露出来。</li> <li>在后期技术评审时,探讨逻辑交互以及上下游数据走向和消息发送流转,串联技术侧疑问点。</li> </ol> <h3><strong>2.2 &nbsp;测试用例覆盖不全面,场景出现遗漏</strong></h3> <ul> <li> <h4><strong>问题分析</strong></h4> </li> </ul> <p>在测试用例设计过程中,容易出现思维受限或者需求盲区,我们不可能完全覆盖用户使用的所有场景,编写测试用例的时不可能把所有的场景都能想周全,把所有的场景下的情况都写成测试用例去模拟、去覆盖这也是不太现实的。</p> <ul> <li> <h4><strong>改进措施</strong></h4> </li> </ul> <ol> <li> <p><strong>用例设计开始之前,列思维导图</strong></p> <p>通过思维导图列出业务流程,前、后端接口逻辑。然后按照PRD和交互文档,依照UI界面切分成大的功能块,然后在大功能块,然后在大功能块再切成小功能块,最后到功能点,每个功能点通过UI、基本功能、边界、内存、数据、交互、接口逻辑等维度开展用例设计导图,并列出需找产品、开发确认的疑点。</p> </li> <li> <p><strong>用例设计完成后组织用例评审</strong></p> <p>a. 组织开发、产品进行测试用例评审,并抛出用例设计时的疑问,通过产品实现角度、数据存储、用户、产品体验角度对用例进行评审完善补充。</p> <p>b. 组织测试组内提前预审测试用例也是非常必须的,对于正式用例评审前会组内进行预审,在版本结束后组织全量用例集合入也会进行串讲用例,特别是一些经验老道或者业务熟悉的老司机们,可以在用例评审上快速的帮忙指出用例的遗漏点,有助于测试人员打开思路,尽可能多的覆盖用户场景,值得注意的是用例评审上遇到不确定的,应立即记录下来作为待办项,结束后及时找相关人员确认,避免猜测不确定。</p> </li> <li> <p><strong>总结用户反馈、完善测试用例流程-下钻测试用例构建以有备无患</strong></p> <p>a. 产品测试发布上线后,对于用户反馈的缺陷,如果缺陷是因为场景设计不全引起的,我们先分析出现问题的场景是必现还是偶现,如果是必现,我们可以通过和技术同学沟通,确认该场景的一些具体复现步骤,确认引入原因,解决方案。</p> <p>b. 对于线上如果出现缺陷需要对测试用例完善:除了补充该场景case外,考虑一些和该场景相关联的场景,将多种场景下测试用例及时完善、评审,增加到用例库中去。</p> <p>c. 针对线上缺陷分析其具体原因做复盘总结,关注线上问题反馈群,及时发现问题、定位问题、分析原因,判断是否为老逻辑引入还是新功能引发问题,精准化补充对应的用例,针对特别场景补充接口自动化、防资损数据狗校验、全量用例集合BVT用例。</p> </li> </ol> <h3><strong>2.3 &nbsp;测试阶段未严格按照测试用例执行</strong></h3> <ul> <li> <h4><strong>问题分析</strong></h4> </li> </ul> <p>按照测试用例执行测试,可以让我们尽可能的不出现遗漏一些测试点。不能因为某一个人或者对某一块业务熟悉简化其测试用例,不严格按照测试用例来执行测试,这样出现了一些遗漏Bug实在是不应该。</p> <ul> <li> <h4><strong>改进措施</strong></h4> <ul> <li> <p>测试用例不一定能保证所有的场景和功能点都能覆盖到,但是严格按照测试用例执行测试,能最大程度上保证产品质量,尽量避免出现缺陷。</p> </li> <li> <p>养成测试纪录习惯:对于测试阻塞用例、测试Fail用例,应该重点关注并记录,在回归测试阶段进行精准回归测试,确保修复Bug导致关联功能引入的新Bug也能被发现。</p> </li> </ul> </li> </ul> <p>虽然测试流程很规范,但是软件质量还是不如意。</p> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-c32a6e2be055885e1ff5adfc7e19c6587ab.png" alt=""></p> <h3><strong>2.4 &nbsp;测试环境、测试资源受限,导致缺陷漏测</strong></h3> <ul> <li> <h4><strong>问题分析</strong></h4> </li> </ul> <p>对于现阶段得物的测试环境问题是及其复杂的,业务系统不是孤立存在的,关联方环环相扣,而且关联系统常常出现不稳定的情况,另外涉及身份证、银行卡等稀缺资源的使用有限,往往测试完一个有效数据废弃一个有效数据,所以我们可以尽可能通过mock、还原客户的实际环境问题。</p> <p>现实毕竟不是真实的环境,由于环境的差异,可能出现很多意想不到的问题,例如:配置问题、数据源问题、以及数据同步问题,这些都是可能只在特性的环境、特定的操作步骤下才会暴露出来,在我们的测试环境还原不出来,只能基于预发环境或者生产环境来验证问题,导致质量可能出现风险隐患。</p> <ul> <li> <h4><strong>改进措施</strong></h4> </li> </ul> <p><strong>1)引入灰度发布测试</strong></p> <p>测试组在预发布环境上进行回归测试,能基本模拟真实环境执行测试环境无法测试的用例,又不影响线上用户的正常使用。</p> <p><strong>2)生产验证环节做好case筛选</strong></p> <p>首先进行生产验证case梳理,生产验证case除了筛选p0+p1级别case进行回归外,还应该包含测试环境mock or 挡板阻塞的测试case,以及后端接口对前端响应的case,在生产回归阶段严格按照生产验证case执行去覆盖真实线上环境场景。</p> <p><strong>3)加强后端以及关联方业务逻辑的了解</strong></p> <p>前端不仅需要了解前端与后端接口的交互业务逻辑,还需了解后端接口与其它关联方的接口交互逻辑,校验判断其给的接口数据是否正确,对测试环境测试用例的覆盖程度有整体的把控度,以确保生产环境的测试用例覆盖做到全面性。</p> <h3><strong>2.5 &nbsp;开发人员引入的新Bug</strong></h3> <ul> <li> <h4><strong>问题分析</strong></h4> </li> </ul> <p>有一些开发人员只会针对你所提交的Bug中问题的描述步骤解决,并不会去排查该问题有可能涉及的所有点,有可能出现解决了这个问题,而引入了一个新的问题。一个不熟悉功能模块的开发人员来修复Bug,因为业务不熟悉,考虑不周全导致无意识的引入新的Bug。</p> <ul> <li> <h4><strong>改进措施</strong></h4> </li> </ul> <p><strong>1)代码review</strong></p> <ul> <li>从代码管理层面:开发修复一个Bug提交代码自测通过准备提测时,开发团队提交代码进行代码review,引入新Bug的可能性概率就会较小,降低风险存在。</li> </ul> <p><strong>2)精准回归测试</strong></p> <ul> <li>从测试自我修养层面:在开发提测后,了解代码改动点,精准分析改动点对相关联的功能点的影响,将开发人员修复的Bug确认验证,并将相关联的功能点尽可能的遍历回归测试到</li> </ul> <p><strong>3)找开发聊聊开发是如何修复这个功能</strong>*</p> <ul> <li>跟开发聊实现很容易从开发的设计中你可以把握到测试的注意点,并记录体现在用例中。例如A开发曾经用某种方式做了B功能,出现了某个Bug,现在B功能用了同样方式实现,那么极有可能之前的Bug还会出现在C功能。</li> </ul> <p><strong>4)覆盖率的实践和应用</strong></p> <ul> <li>增加开发冒烟执行代码覆盖率,根据覆盖率数据分析有那些冒烟用例未覆盖到,是方法未覆盖到、还是类未覆盖到或者是异常逻辑的校验未回归到,用开发自测和覆盖率的方式降低其新Bug的引入。</li> </ul> <h3><strong>2.6 &nbsp;探索性测试环节欠缺</strong></h3> <ul> <li> <h4><strong>问题分析</strong></h4> </li> </ul> <p>我们发现的很多Bug都不是按测试用例执行发现出来的,都是在测试过程中随意测试发现的,而这些步骤在测试用例中并未体现,我们的测试用例不可能覆盖所有的场景。</p> <ul> <li> <h4><strong>改进措施</strong></h4> </li> </ul> <p><strong>1)准入测试通过后进行ET测试</strong></p> <ul> <li>在测试准入测试完成进入SIT测试阶段:一般来说,ET测试是最容易发现Bug的,所以在测试准入测试完成进入SIT测试阶段,先进行一轮探索性测试,使的大部分的Bug先在测试前期暴露出来,让Bug累计数量达到一定的峰值,尽早发现Bug,质量越高。</li> </ul> <p><strong>2)UAT</strong> <strong>测试之前进行组内ET测试</strong></p> <ul> <li>SIT测试进入尾声,UAT测试之前组织一次组内ET测试,让组内不同的测试用不同的测试方式,测试思维,测试经验,测试习惯进行探索测试,能发现一些由于思维定势局限原因导致漏测的Bug、诡异的Bug或者使用不合理的地方。</li> </ul> <p><strong>3)精准化测试</strong></p> <ol> <li> <p>精准测试的测试用例聚类分析功能,可以有效地发现“测试的错误”。例如一个用例执行步骤错误,它的聚类结果必然会发生变化,管理者通过系统分析的结果就可以发现并纠正这一类的错误,而之前可能需要在现场回归反复的确认。</p> </li> <li> <p>精准测试的核心技术要点是测试用例与代码的追溯技术。这项技术简单来说就是当功能执行完成以后对应的整体代码执行情况就会立即产生,即当点击一个测试用例,就立即追踪到对应的代码和模块。</p> </li> <li> <p>精准测试测试漏洞分析功能,适用于敏捷测试。它可以基于程序静态数据和动态运行数据,自动分析软件缺陷最高风险的位置,引导首先对于高风险的模块完成覆盖,在有限时间内完成最具有风险的模块的覆盖测试。</p> </li> </ol> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-83157230fab239decb4eb6cf7e820e58bdf.png" alt=""></p> <h2><strong>三、对于开发角度侧思考</strong></h2> <h3><strong>3.1 &nbsp;自测背景</strong></h3> <p>开发人员做好自测,非常必要,也是大趋势。前期都是开发自测,后期才是用户体验方面的测试。从成本和时间上分析,Bug越晚发现修复成本越高;从修改的效率来讲,越早处理会越快。一个优秀的开发者,自测的Bug一定会多于测试发现的Bug,也就是轮到测试的时候Bug数量相当少。</p> <h3><strong>3.2 &nbsp;疑难问题思考</strong></h3> <ol> <li> <p>时间和进度太紧张,排期紧凑。</p> </li> <li> <p>对自己代码过于自信,自认为有很强的健壮性,不忍心去修改。</p> </li> <li> <p>认为这是测试的责任,多度依赖测试。</p> </li> <li> <p>不知如何有效的做好自测,覆盖全面。</p> </li> <li> <p>开发冒烟测试对于QA创建指定的用例理解不透彻,执行简约。</p> </li> </ol> <h3><strong>3.3 &nbsp;思维转变</strong></h3> <ol> <li> <p>代码质量、项目质量均是我们的责任。</p> </li> <li> <p>测试和开发人员思考问题不同,开发是在制造软件,测试是在破坏软件,想办法去找出问题。</p> </li> <li> <p>任何功能都有正常场景和异常场景,多数使用等价类和边界值去选择数据,覆盖全面。</p> </li> <li> <p>不要相信任何开发的代码是无Bug。</p> </li> <li> <p>走出具体实现时用的开发思维,站在需求和用户的角度去自测是否通过,假如自己是用户去测试你的功能。</p> </li> </ol> <h3><strong>3.4 &nbsp;不仔细认真自测带来的痛处和隐患</strong></h3> <ol> <li> <p>需求遗漏:一旦被用户发现此问题,用户印象会大打折扣,可能直接从开始使用即放弃使用,将带来非常大的客户流失。</p> </li> <li> <p>功能事故:主流程功能没有测试到位,或者异常场景没有测试到位,导致线上频繁报错,体验极度不好,直接认为就是事故。</p> </li> <li> <p>需求延期上线:如果自测不充分,测试花大量的时间去沟通低等级bug,甚至主流程走不下去,这样无疑会给开发带来返工、重复测试、耗时、需求延期、项目延期等一系列问题。</p> </li> </ol> <h3><strong>3.5 &nbsp;制定自测报告规范</strong></h3> <ul> <li><strong>功能模块介绍及背景介绍</strong></li> </ul> <ol> <li> <p>功能、背景介绍</p> </li> <li> <p>使用用户群体介绍</p> </li> </ol> <ul> <li><strong>环境信息</strong></li> </ul> <ol> <li> <p>版本号</p> </li> <li> <p>Hosts、代码发布分支</p> </li> <li> <p>预发or正式</p> </li> <li> <p>功能设计文档以及UI设计图等</p> </li> <li> <p>数据库数据同步、环境配置、开关设定等</p> </li> </ol> <ul> <li><strong>梳理好的自测点</strong></li> </ul> <ol> <li> <p>编写代码时候记录的业务点和测试点</p> </li> <li> <p>需求变更的自测点</p> </li> <li> <p>正向、逆向、异常场景测试点</p> </li> <li> <p>兼容性</p> </li> <li> <p>开发此功能是否会对其他功能造成影响,一行代码是否会引发新的问题出现</p> </li> </ol> <ul> <li><strong>自测实际结果:</strong></li> </ul> <ol> <li> <p>高等级Bug数量、影响冒烟核心流程</p> </li> <li> <p>中等级Bug数量、串联流程链路</p> </li> <li> <p>低等级Bug数量、页面展示UI效果</p> </li> <li> <p>开发冒烟自测阶段覆盖率</p> </li> <li> <p>一轮、集成阶段覆盖率</p> </li> </ol> <ul> <li><strong>期望结果:</strong></li> </ul> <ol> <li> <p>符合测试SOP规定准出标准</p> </li> <li> <p>冒烟自测以及集成阶段覆盖率标准</p> </li> <li> <p>测试阶段Bug数量的控制</p> </li> <li> <p>上线后Bug数量的控制,质量月复盘满足数量控制标准</p> </li> </ol> <h2><strong>四、总结</strong></h2> <p>缺陷漏测发生后我们需要深入分析漏测的Bug,思考哪方面做的不够,是业务逻辑理解误差?用例评测遗漏?技术方案存在不合理?思考设计用例方向出现了偏差?多问一些几个为什么,换位思考角度想问题,合理设计评测。确保类似的Bug能被预防提前发现暴露出来,从而尽可能的降低缺陷的产生,提高产品质量。在每个不同阶段做好用例测试计划执行,增加精细化测试以及探索性测试环节,需要开拓新的测试思想思维,走出惯用常规的测试思想。同时也要站在开发侧、编写代码设计的思维逻辑去考虑,降低可能在测试阶段出现Bug漏测、遗漏的出现,开发侧也需严格执行自测和覆盖率SOP要求准出。</p> <p>*<strong>文</strong> <strong>/Viki</strong>&nbsp;</p> <p>要是觉得文章对你有帮助的话,欢迎评论转发点赞~</p> 得物技术 2023-05-29 https://www.v2tn.com/content/1685370451022380
技术分享 | 多测试环境的动态伸缩实践 https://www.v2tn.com/content/1685291211394561 <p>本文将从敏捷研发团队的环境需求与痛点出发,分享如何基于云构建可弹性伸缩的自动化生成式多测试环境;更在经济效益层面,提供了多种成本优化方案,以满足研发团队低成本、高效益的多测试环境运行目标。</p> <h2>一、当前遇到的环境问题</h2> <p>初期,根据实际研发需要,LigaAI主要应用了以下四套环境:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/90c758531b6b4ab68e2da3c8080599bc~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <ul> <li>Dev环境是开发环境,专供前/后端开发人员进行功能开发自测、联调等;</li> <li>Sit环境为测试环境,供测试成员进行迭代功能验收;</li> <li>Pre环境为预发布环境,主要承担整体测试、回归测试等;</li> <li>最后,Prod环境为生产环境。</li> </ul> <p>随着团队规模不断扩大、业务组划分走向清晰,以及微服务拆分愈发精细,环境资源开始逐步缩紧,资源紧张带来的冲突频繁制约着团队发展。</p> <blockquote> <ul> <li>对迭代有风险的复杂需求需要剥离迭代,进行单独测试;</li> <li>开发人员需要不同的Dev环境进行联调;</li> <li>迭代小组的迭代进度各异,需要分批提测;</li> <li>紧急Hotfix急需测试,但环境已被占用;</li> <li>需要进行系统压测,却缺乏一套压测环境;</li> </ul> </blockquote> <p>为缓解环境资源紧张问题,LigaAI对原有的Dev环境和Sit环境做了如下扩展。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e6cc341574de4ac884e5a1a2a857f4dd~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>如此虽一定程度上满足了不断增加的环境需求,但不可避免地导致了其他问题。因此,针对以下环境需求痛点,LigaAI着手搭建了一套高弹性、可伸缩的测试环境。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5f61a7d08e54472ab791b731730b0992~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2>二、测试环境的改造目标</h2> <p>开始正式改造前,LigaAI结合研发流程和环境需求,对目标测试环境提出了几点要求:</p> <ul> <li><strong>多环境</strong>:针对不同的测试场景,可以提供不同的测试环境。</li> <li><strong>互相区隔</strong>:数据、配置信息和应用访问在不同环境之间要相互隔离。</li> <li><strong>高效稳定</strong>:环境要保持稳定且高效地运转,不能影响正常迭代进度。</li> <li><strong>低成本</strong>:产生尽可能较低的额外成本,任何时期都要将资源用在刀刃上。</li> <li><strong>可复用</strong>:针对特殊需求可快速扩展新环境;简化测试环境维护,让团队聚焦研发与测试。</li> </ul> <h2>第一步:测试环境的标准化改造</h2> <h3>Step 1:搭建底层基础设施</h3> <p>围绕弹性、扩展和部署等关键词,LigaAI最终选用Amazon EKS作为环境伸缩的底层基础设施。</p> <p>Amazon EKS即Amazon Elastic Kubernetes Service,是一项完全托管的服务。无需安装、操作或维护集群也可轻松运行Kubernetes,而其内置的控制面板则为LigaAI的集群管理提供了便利。</p> <h3>Step 2:规范中间件资源</h3> <p>为方便应用接入,我们梳理了系统中需要改造或命名规范化的基础资源和中间件,包括域名命名、数据库地址、消息队列、Redis和Elasticsearch等。</p> <p>命名规范化可以以环境名称为统一标识,采用「<strong>资源名称_环境名称</strong>」等形式完成。</p> <h3>Step 3:应用改造</h3> <p>下一步,依据梳理好的基础资源和中间件规范,重新整理并统一测试环境配置信息,规范化应用配置和持久化数据。</p> <p>应用改造目标是,<strong>只需注入环境名称,即可替换所有与环境相关的配置信息</strong>,如回调地址、消息队列、数据库信息等;而持久化的数据不应保存与环境信息相关的数据。</p> <p>该阶段可能涉及到一部分代码改造,需要开发团队参与配合。</p> <h3>Step 4:制作环境模板</h3> <p>想要自动生成环境,首先必须有一套含有持久化数据、配置文件和应用包的环境模板;其中,应用包数据包括后端镜像和前端资源包。</p> <p>在本次改造中,LigaAI指定Pre环境作为基准环境模板来源。</p> <h3>Step 5:一键搭建环境</h3> <p>为最大程度提高产研团队效率,环境搭建必须方便快捷,且满足可复用要求。</p> <p>将环境搭建流程的各个环节脚本化,并将这些脚本集成到流水线任务当中,实现环境搭建的一键生成效果;其中,将部分流程并行处理,也会加快环境生成速度。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/225e8c59e98d45818ad329d614add8b3~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3>Step 6:环境登记责任人</h3> <p>除一键生成环境外,制定标准化的环境管理流程也很重要。明确环境负责人,将环境生成、重置与释放流程集成到运维平台,让申请信息可视化;</p> <p>同时,通过信息通知集成IM,支持环境生成/释放信息、环境到期提醒等通知的及时触达。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c7b6e48e8c4140aba87e84bee2703ee7~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2>四、标准化改造成果:环境生成自动化</h2> <p>至此,测试环境的标准化改造告一段落,而LigaAI也成功打通了环境模板生成流程和环境申请流程的数据传递通道。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3cfdb16a4b79460eb41a69875c2d46f8~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3>左边:环境模板生成流程</h3> <blockquote> <p>发布生产后,触发模板构建任务;</p> <p>通过提取Pre环境的数据,找出当前的镜像信息,打上Tag并标记为模板镜像;</p> <p>再将环境模板所需要的数据库、配置文件和前端资源等数据上传到Amazon S3进行保存。</p> </blockquote> <h3>右边:环境申请流程</h3> <blockquote> <p>环境申请人先在运营平台登记申请,填写使用时间和使用范围;</p> <p>提交申请后,触发任务:从Amazon S3拉取配置数据,初始化中间件资源,从镜像仓库拉取模板镜像部署应用,一键生成环境;</p> <p>环境到期后会自动释放,如需继续使用,提交延长登记信息即可。</p> </blockquote> <p>环境生成的标准化改造通过流水线任务自动搭建、环境自动释放和申请人登记,解决了环境需求的三大痛点。想要进一步解决环境资源紧缺或浪费的问题,需要继续完成测试环境的弹性伸缩改造。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3912479a22bf4c1d99f02ac515595de6~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2>第二步:测试环境的弹性伸缩改造</h2> <p>容器资源主要分为Pod级别和Node级别。每个Pod包含一个或多个应用容器,并以整体的形式在Node之上运行。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d657b1babf024983b28e18d8eb1778e3~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>与资源分类对应,资源伸缩也有两种模式:</p> <ul> <li>Pod级别的资源伸缩为HPA,是Kubernetes的内置服务,主要用于副本数量的调整;</li> <li>Node级别的资源伸缩为Cluster Autoscaler,非Kubernetes内置服务,需要手动部署Deployment安装;</li> </ul> <p>想要让服务器资源满足变化频繁的研发环境需求,则需要对Node级别进行弹性伸缩改造。</p> <p>Amazon EC2 Auto Scaling groups(以下简称自动伸缩组)提供了弹性扩展服务器实例的功能,支持设置服务器的初始生成数量、最小数量以及最大数量限制。</p> <p>当扩展策略生效时,自动伸缩组会在指定的最小和最大容量值之间调整组的所需容量,并根据需要启动或终止实例。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e13d38f14b064a8e89d5b5ef0f31fa55~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3>痛点4:服务器资源不足时,如何扩容?</h3> <p>环境申请成功后,Pod数量增加,但因节点资源饱和/不足,此时新的Pod会处于Pending状态。</p> <p>Cluster Autoscaler定期(默认间隔 10 秒)检测节点资源的使用情况。一旦监测到Pending状态的Pod,便会触发节点扩容,调用Cloud Provider,创建新的Node以满足增加的环境需求。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/69c2e513882547e5b2a753fb20dd01d0~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3>痛点5:服务器资源过剩时,如何缩容?</h3> <p>测试完成后,环境资源释放,Pod被删除。此时,Node资源呈闲置状态。</p> <p>当检测到一个Node已超过 10 分钟没有执行任何扩展操作,或资源利用率均低于 50% 时,Cluster Autoscaler会控制自动伸缩组进行回收节点,自动将其删除;原来的Pod也会自动调度到其他Node上。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9aba9bc34d064e8cb96efdd285aca7bb~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>以上,Cluster Autoscaler通过Cloud Provider插件,操作自动伸缩组完成服务器资源的扩展与回收,达成测试环境的弹性伸缩改造。</p> <h2>六、如何实现低成本,高效运行环境?</h2> <h3>1. 中间件资源复用</h3> <p>云环境下,对数据库、Redis、Elasticsearch、配置中心和注册中心等中间件资源进行复用,可大幅节省使用成本和资源,降低环境扩展难度。</p> <p>比如,在一个数据库实例上,以环境名称为索引标识,创建不同环境的数据库,以节省资源。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/161ab003246744fb8441b4971a41aed0~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3>2. 合理分配资源</h3> <p>此外,还可以通过以下几个方面,控制云服务器上的成本支出。</p> <p><strong>第一,合理分配CPU和内存的Pod资源预留与资源限制。</strong> 资源预留(Requests)表示Pod需要占用的最小资源,即节点上必须有大于Request值的资源,才能调度这个节点;而资源限制(Limits)则表示Pod可使用资源的最大值,当容器占用资源超过Limit值时,就会被终止或重启。</p> <p>CPU是弹性资源,而大部分IO密集型应用在测试时对CPU的使用率和消耗都比较低,因此建议将CPU的Requests设置小一些,将Limits调大一点。</p> <p>Java应用分配内存则可以通过分析GC日志、应用监控信息、JVM监控信息等,根据GC频率和GC耗时的表现,找到一个可接受的内存设置平衡点,用较小的内存满足当前的服务需要。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ddbe84753ce44764a8c020f990942cf6~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>第二,关注节点的配置比例和大小选取</strong>。CPU和内存的节点配置比例需要根据实际业务系统的需求确定。比例设置原则是避免CPU或内存成为明显的短板,常见的应用比例是 1:4 或者 1:8。</p> <p>节点的选择上,一方面要避免选择配置低的小节点。因为节点上需要部署Kubernetes的基础组件,这会消耗固定的资源,且节点越多,整体开销和成本越大;此外,过小的节点还可能出现资源碎片的问题,所以建议适当挑选大一些的节点。</p> <p>另一方面,切忌盲目追求大节点。大节点允许的Pod数量较多,一旦节点出现问题,影响范围也会更大。同时,大节点的自动伸缩成本更高,容易出现「杀鸡用牛刀」的情况。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ff164dee52fb479095af178670267c0f~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>第三,奉行勤俭节约原则。</strong> 一次性运行的任务或执行频率较低的周期任务,可以通过K8S Job和CronJob执行。另外,资源节约意识也表现在环境不用时及时回收、没有特别情况不随便申请环境、避免非常规环境空置等习惯之中。</p> <h3>3. 控制云上的成本</h3> <p>LigaAI的测试环境改造采用了多项亚马逊云科技服务,因此我们也通过减少云服务商的成本费用,进一步实现低成本的高效运行。</p> <p><strong>首先,挑选合适的区域很重要</strong>。就亚马逊云服务而言,不同区域的费用标准也会有所差异。可以多多对比中国区和外国区,或宁夏区域和北京区域的相关费用标准,选择最合适的区域服务。</p> <p><strong>其次,还可以关注云服务器的不同定价方案</strong>。以Amazon EC2云服务为例,我们主要考虑按需实例、预留实例和竞价实例三种定价方案。</p> <ul> <li>按需实例/On-Demand Instances:按小时或秒(最少 60 秒)收费。</li> <li>预留实例/Reserved Instances:类似按年付费;相比按需实例,最高可提供 72% 折扣。</li> <li>竞价实例/Spot Instances:在服务器需求不高时,可出售空闲服务器资源;相比按需实例,最多可享 90% 折扣。</li> </ul> <p>采用「预留实例+竞价实例」的组合方式,也能进一步实现经济效益最大化。</p> <blockquote> <p>对于固定的环境,提前计算好需要的服务器数量,申请预留实例,并将其设置为自动伸缩组中的最小实例数量;再将额外的扩展环境设置为最大数量,以此实现弹性扩容。</p> <p>对稳定性要求不高的环境或应用(如开发环境),可以通过Spot自动伸缩组进行环境扩容。</p> </blockquote> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/217dac60c306425f8f1120144b45a69e~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>01 配置节点亲和性和污点</strong></p> <p>设置节点亲和性或污点,让对的Pod被调度到正确的节点上。节点亲和性使得Pod被吸引到一类具有特定标签的节点上,而节点污点(Taint)则相反,它使得Pod避免被调度到这些节点上。</p> <p><strong>通过将需要稳定运行的Pod固定在按需实例或预留实例的节点组上,将可容忍中断的Pod限制在Spot节点组上,也可满足成本控制的需要。</strong></p> <p>为了方便环境回收时的节点释放,按环境名称设置Pod亲和性,将同一环境的Pod尽量放置到相同的节点,减少节点中的Pod转移,提高节点回收率。</p> <p><strong>02 如何降低Spot节点中断的影响?</strong></p> <p><strong>第一,选择多个可用区和多种实例类型。</strong> 注意,同一个节点组的实例类型的CPU核心数量跟内存大小必须一致,这样会有更充足的资源。</p> <p><strong>第二,设置Pod优先级。</strong> 对非关键Pod设置低优先级,可以在节点回收时,率先将重要的Pod转移到其它空闲资源中去;</p> <p><strong>第三,还可以在节点关闭前,先将Pod调度转移</strong>。具体实现路径如下:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0d9c1fd3c5d04ab49e4e4771c9991f44~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <blockquote> <p>首先,开启自动伸缩组的「容量再平衡设置」。开启后,如果Spot节点有中断风险,自动伸缩组就会提前发出容量再平衡通知,并重新分配一个新的Spot节点。</p> <p>旧节点关闭前两分钟,自动伸缩组会发出终止实例的通知(需手动开启相应的通知配置)。</p> <p>而在Kubernetes中,我们需要部署AWS Node Termination Handler服务,并通过它来接收事件,驱逐旧节点里的Pod;Pod驱逐完成后,再关闭旧的节点。</p> </blockquote> <p>以上步骤可以基本保证Spot节点的相对稳定性。</p> <h3>4. 账单费用监控告警</h3> <p>最后,做好费用的监控预警也很重要。以下服务可用于监控费用明细,提供资源优化支撑,也可以对账单费用突增、预留实例覆盖率进行告警通知。</p> <ul> <li>Amazon Cost Explorer</li> <li>Amazon Budgets</li> <li>AWS Tweaker</li> </ul> <hr> <p>本文内容整理自Apps Everywhere系列活动 - 深圳站(线上直播)的主题分享。该活动由亚马逊云科技User Group举办,聚焦云原生开发技术,探索云原生技术下的测试、交付、安全等话题的全新思维碰撞。</p> <p>未来,LigaAI将持续为开发者社区提供高质量技术分享,与更多开发者和团队一起探索高效益的研发管理之道。</p> <blockquote> <p>了解更多敏捷开发、项目管理、行业动态等消息,关注我们 [LigaAI<a href="https://my.oschina.net/osadmin">@oschina</a>](<a href="https://my.oschina.net/u/5057806">https://my.oschina.net/u/5057806</a>)&nbsp;或点击<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.ligai.cn%2F%3Futm_source%3Dmkt%26utm_medium%3Doschina" target="_blank">LigaAI - 新一代智能研发协作平台</a>,在线申请体验我们的产品。</p> </blockquote> LigaAI 2023-05-29 https://www.v2tn.com/content/1685291211394561
【手把手】这篇全链路压测实践教程 https://www.v2tn.com/content/1685209358651933 <p>Hello,大家好呀,前两篇文章,我们说了下关于全链路压测的意义、整体架构,以及5种压测的方案。</p> <p>前面两篇基本都属于比较理论的内容,今天这篇咱们来点实践的东西,手把手带你搞出一个压测来</p> <p>如果不清楚之前两篇的文章的小伙伴,可以先看下,在这里</p> <ul> <li><strong><a href="https://my.oschina.net/jiagoushi/blog/5577221" title="大厂钟爱的全链路压测有什么意义?四种压测方案详细对比分析">大厂钟爱的全链路压测有什么意义?四种压测方案详细对比分析</a></strong></li> <li><strong><a href="https://my.oschina.net/jiagoushi/blog/5577570" title="【代码级】全链路压测的整体架构设计,以及 5 种实现方案(流量染色、数据隔离、接口隔离、零侵入、服务监控)">【代码级】全链路压测的整体架构设计,以及 5 种实现方案(流量染色、数据隔离、接口隔离、零侵入、服务监控)</a></strong></li> </ul> <h3>7 环境准备</h3> <h4>7.1 环境服务列表</h4> <blockquote> <p>需要在虚拟机或者linux服务器启动运行环境</p> </blockquote> <table> <thead> <tr> <th>服务</th> <th>ip</th> <th>端口</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>mysql</td> <td>172.18.0.10</td> <td>3306</td> <td>数据库服务</td> </tr> <tr> <td>rabbitMQ</td> <td>172.18.0.20</td> <td>5672,5672</td> <td>RabbitMQ消息服务</td> </tr> <tr> <td>redis</td> <td>172.18.0.30</td> <td>6379</td> <td>Redis缓存服务</td> </tr> <tr> <td>nacos</td> <td>172.18.0.40</td> <td>8848</td> <td>微服务注册中心</td> </tr> <tr> <td>skywalking</td> <td>172.18.0.50</td> <td>1234,11800,12800</td> <td>链路追踪APM服务端</td> </tr> <tr> <td>skywalking-ui</td> <td>172.18.0.60</td> <td>8080</td> <td>链路追踪APM服务UI端</td> </tr> </tbody> </table> <h4>7.2 应用服务列表</h4> <blockquote> <p>应用服务可以单独部署或者在idea中启动</p> </blockquote> <table> <thead> <tr> <th>服务</th> <th>ip</th> <th>端口</th> <th>备注</th> </tr> </thead> <tbody> <tr> <td>order-service</td> <td>127.0.0.1</td> <td>8001</td> <td>订单服务</td> </tr> <tr> <td>account-service</td> <td>127.0.0.1</td> <td>8002</td> <td>账户服务</td> </tr> <tr> <td>storage-service</td> <td>127.0.0.1</td> <td>8003</td> <td>数据存储服务</td> </tr> <tr> <td>notice-service</td> <td>127.0.0.1</td> <td>8004</td> <td>通知服务</td> </tr> </tbody> </table> <h4>7.3 docker-compose 编排环境</h4> <blockquote> <p>我们的docker-compose只对环境进行了搭建,具体微服务在本地运行或者在容器运行都可以。</p> </blockquote> <pre><code>version: '2' services: mysql: image: mysql:5.7 hostname: mysql container_name: mysql networks: docker-network: ipv4_address: 172.18.0.10 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root volumes: - "/tmp/etc/mysql:/etc/mysql/conf.d" - "/tmp/data/mysql:/var/lib/mysql" rabbitMQ: image: rabbitmq:management hostname: rabbitMQ container_name: rabbitMQ networks: docker-network: ipv4_address: 172.18.0.20 ports: - "5672:5672" - "15672:15672" redis: image: redis hostname: redis container_name: redis networks: docker-network: ipv4_address: 172.18.0.30 ports: - "6379:6379" volumes: - "/tmp/etc/redis/redis.conf:/etc/redis/redis.conf" - "/tmp/data/redis:/data" command: redis-server /etc/redis/redis.conf nacos: image: nacos/nacos-server hostname: nacos container_name: nacos depends_on: - mysql networks: docker-network: ipv4_address: 172.18.0.40 ports: - "8848:8848" environment: MODE: standalone volumes: - "/tmp/etc/nacos/application.properties:/home/nacos/conf/application.properties" skywalking: image: apache/skywalking-oap-server hostname: skywalking container_name: skywalking networks: docker-network: ipv4_address: 172.18.0.50 ports: - "1234:1234" - "11800:11800" - "12800:12800" skywalkingui: image: apache/skywalking-ui hostname: skywalkingui container_name: skywalkingui depends_on: - skywalking networks: docker-network: ipv4_address: 172.18.0.60 environment: SW_OAP_ADDRESS: 172.18.0.50:12800 ports: - "8080:8080" networks: docker-network: ipam: config: - subnet: 172.18.0.0/16 gateway: 172.18.0.1 </code></pre> <h4>7.4 初始化数据</h4> <ol> <li> <p>初始化用户数据以及产品数据</p> </li> <li> <p>将feign,hystrix,ribbon等统一配置配置到nacos</p> <pre><code># 配置超时时间 feign: hystrix: enabled: true #开启熔断 httpclient: enabled: true hystrix: threadpool: default: coreSize: 50 maxQueueSize: 1500 queueSizeRejectionThreshold: 1000 command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 60000 ribbon: ConnectTimeout: 10000 ReadTimeout: 50000 </code></pre> </li> </ol> <h3>8 全链路压测测试</h3> <h4>8.1 jmeter配置</h4> <blockquote> <p>配置好压测数据,并且配置压测线程数1000 进行10轮压测</p> </blockquote> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-bf31379e2643b2328561b9ddea429ca84ac.png" alt="file"></p> <h4>8.2 第一轮压测</h4> <h5>8.2.1 链路分析优化</h5> <blockquote> <p>我们找到一个调用时长1S左右的链路,分析发现在存储服务调用时,耗时较长,但是数据库调用耗时并不长,基本说明是存储服务的连接池耗尽导致调用过长。</p> </blockquote> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-e4cfa8b9a680f25f04f5c7421e11eb7fe44.png" alt="file"></p> <h5>8.2.2 数据库连接池优化</h5> <blockquote> <p>调整存储服务的连接池,由原来的最大10 改为100</p> </blockquote> <pre><code>initialSize: 10 minIdle: 20 maxActive: 100 </code></pre> <h4>8.3 第二轮压测</h4> <blockquote> <p>结果已经由原来的服务内部的耗时 变为了fegin的耗时,这种情况下可以考虑使用fegin的连接池优化或者新增节点</p> </blockquote> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-a293e2904ce703d32046789ae650c7bfeaa.png" alt="file"></p> <h5>8.3.1 观察消费节点</h5> <blockquote> <p>发现消费速度很慢,产生了大量消息堆积</p> </blockquote> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-a8620874ca4cc6112b35a4edc8e1df3ab12.png" alt="file"></p> <blockquote> <p>检查<code>storage-service</code>的<code>actualPlaceOrder</code>端点信息</p> </blockquote> <p>发现平均响应时间在200ms左右</p> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-76aa4e4c2dbb104123ad1a3c70604cef2e1.png" alt="file"></p> <p>检查断点链路<code>/storage/order/actualPlaceOrder</code></p> <blockquote> <p>发现是事务提交慢造成的,这个时候就需要优化mysql服务器了</p> </blockquote> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-e578ea12bc62ac87f7e95ea54af153a78d5.png" alt="file"></p> <h3>9 Skywalking 使用</h3> <h4>9.1 Skywalking 模块栏目</h4> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-3beb8b0a09b084988e701a8f9d231285e04.png" alt="file"></p> <blockquote> <p>Skywalking web UI 主要包括如下几个大的功能模块:</p> </blockquote> <ul> <li>仪表盘:查看被监控服务的运行状态</li> <li>拓扑图:以拓扑图的方式展现服务直接的关系,并以此为入口查看相关信息</li> <li>追踪:以接口列表的方式展现,追踪接口内部调用过程</li> <li>性能剖析:单独端点进行采样分析,并可查看堆栈信息</li> <li>告警:触发告警的告警列表,包括实例,请求超时等。</li> <li>自动刷新:刷新当前数据内容。</li> </ul> <h4>9.2 仪表盘</h4> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-a380a48ee5e84c3a0bb6e03a46d27e3a47f.png" alt="file"></p> <ul> <li>第一栏:不同内容主题的监控面板,应用/数据库/容器等</li> <li>第二栏:操作,包括编辑/导出当前数据/倒入展示数据/不同服务端点筛选展示</li> <li>第三栏:不同纬度展示,服务/实例/端点</li> </ul> <h4>9.3 展示栏</h4> <h5>9.3.1 Global全局维度</h5> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-541af527fa5a2c5b90eb60cdac5bdc47f99.png" alt="file"></p> <ul> <li>第一栏:Global、Server、Instance、Endpoint不同展示面板,可以调整内部内容</li> <li>Services load:服务每分钟请求数</li> <li>Slow Services:慢响应服务,单位ms</li> <li>Un-Health services(Apdex):Apdex性能指标,1为满分。</li> <li>Global Response Latency:百分比响应延时,不同百分比的延时时间,单位ms</li> <li>Global Heatmap:服务响应时间热力分布图,根据时间段内不同响应时间的数量显示颜色深度</li> <li>底部栏:展示数据的时间区间,点击可以调整。</li> </ul> <h5>9.3.2 Service服务维度</h5> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-cc1df4e171614930614345012fa347e1d96.png" alt="file"></p> <ul> <li>Service Apdex(数字):当前服务的评分</li> <li>Service Apdex(折线图):不同时间的Apdex评分</li> <li>Successful Rate(数字):请求成功率</li> <li>Successful Rate(折线图):不同时间的请求成功率</li> <li>Servce Load(数字):每分钟请求数</li> <li>Servce Load(折线图):不同时间的每分钟请求数</li> <li>Service Avg Response Times:平均响应延时,单位ms</li> <li>Global Response Time Percentile:百分比响应延时</li> <li>Servce Instances Load:每个服务实例的每分钟请求数</li> <li>Show Service Instance:每个服务实例的最大延时</li> <li>Service Instance Successful Rate:每个服务实例的请求成功率</li> </ul> <h5>9.3.3 Instance实例维度</h5> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-d4742006dfbe07e10abf52cff58e4da37d8.png" alt="file"></p> <ul> <li>Service Instance Load:当前实例的每分钟请求数</li> <li>Service Instance Successful Rate:当前实例的请求成功率</li> <li>Service Instance Latency:当前实例的响应延时</li> <li>JVM CPU:jvm占用CPU的百分比</li> <li>JVM Memory:JVM内存占用大小,单位m</li> <li>JVM GC Time:JVM垃圾回收时间,包含YGC和OGC</li> <li>JVM GC Count:JVM垃圾回收次数,包含YGC和OGC</li> <li>CLR XX:类似JVM虚拟机,这里用不上就不做解释了</li> </ul> <h5>9.3.4 Endpoint端点(API)维度</h5> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-c8e7b7fb398442aa9bb8661cfae9a1bf83e.png" alt="file"></p> <ul> <li>Endpoint Load in Current Service:每个端点的每分钟请求数</li> <li>Slow Endpoints in Current Service:每个端点的最慢请求时间,单位ms</li> <li>Successful Rate in Current Service:每个端点的请求成功率</li> <li>Endpoint Load:当前端点每个时间段的请求数据</li> <li>Endpoint Avg Response Time:当前端点每个时间段的请求行响应时间</li> <li>Endpoint Response Time Percentile:当前端点每个时间段的响应时间占比</li> <li>Endpoint Successful Rate:当前端点每个时间段的请求成功率</li> </ul> <h4>9.4 拓扑图</h4> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-3e87b11551dac4146ed93cba1382d214ed4.png" alt="file"></p> <ul> <li>1:选择不同的服务关联拓扑</li> <li>2:查看单个服务相关内容</li> <li>3:服务间连接情况</li> <li>4:分组展示服务拓扑</li> </ul> <h4>9.5 追踪</h4> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-d3c5ed97ca667f5828a8c646779bc960361.png" alt="file"></p> <ul> <li>左侧:api接口列表,红色-异常请求,蓝色-正常请求</li> <li>右侧:api追踪列表,api请求连接各端点的先后顺序和时间</li> </ul> <h4>9.6 性能剖析</h4> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-b3a9cccb8f569938a5d7db57e56f5d7b243.png" alt="file"></p> <ul> <li>服务:需要分析的服务</li> <li>端点:链路监控中端点的名称,可以再链路追踪中查看端点名称</li> <li>监控时间:采集数据的开始时间</li> <li>监控持续时间:监控采集多长时间</li> <li>起始监控时间:多少秒后进行采集</li> <li>监控间隔:多少秒采集一次</li> <li>最大采集数:最大采集多少样本</li> </ul> <blockquote> <p>查看监控结果</p> </blockquote> <p><img style='max-width:100%' src="https://oscimg.oschina.net/oscnet/up-14bea7c52059605a2bbf6c6366e2c54a573.png" alt="file"></p> <blockquote> <p>本文由<code>传智教育博学谷</code>教研团队发布。</p> <p>如果本文对您有帮助,欢迎<code>关注</code>和<code>点赞</code>;如果您有任何建议也可<code>留言评论</code>或<code>私信</code>,您的支持是我坚持创作的动力。</p> <p><strong>转载请注明出处!</strong></p> </blockquote> 博学谷狂野架构师 2023-05-28 https://www.v2tn.com/content/1685209358651933
2022 年全球十大最佳自动化测试工具 https://www.v2tn.com/content/1685197809089907 <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">自动化测试是指运行软件程序后,自动执行测试用例并在没有任何人为干预的情况下产生测试结果。&nbsp;它比手动测试更优越的地方在于,很大程度上节省了人力和时间,并且在测试中没有或者少有错误。此外,还可以多次测试相同的应用程序,从而最大限度地减少冗余的手动工作。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">本文旨在推荐一些在全球广泛使用的测试自动化工具,其中既有商业软件也有开源软件,不过即使是商业软件,大部分都可以免费试用。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">1</span></span><span><span style="color:#494949">、 LambdaTest</span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="51" src="https://oscimg.oschina.net/oscnet/up-d2f3d30e13e8eab5a26013170ddb8d913b2.png" width="300"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">LambdaTest </span></span><span><span style="color:#494949">是用于桌面和 Web 应用程序的自动化测试工具。使用 </span></span><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.softwaretestinghelp.com%2Fbrowser-testing-with-lambdatest%2F" target="_blank"><span><span style="color:#70b1e7">LambdaTest</span></span></a><span><span style="color:#494949">,可以在 2000 多种桌面和移动浏览器上执行手动和自动跨浏览器测试,支持 Python、Java、Javascript 等各种语言。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">此外,用户可以通过并行执行将测试时间减少一半,还可以在超过 27 个国家/地区(包括印度、日本、美国、加拿大、德国、英国、澳大利亚等)测试地理标记、定位、锁定等等。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.lambdatest.com%2Fselenium-automation%3Futm_source%3DSTH%26utm_medium%3DListing%26utm_campaign%3DAutomation-tools%26utm_term%3D" target="_blank"><span style="color:#70b1e7">访问 LambdaTest </span><span style="color:#70b1e7">网站</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">2</span></span><span><span style="color:#494949">、TestComplete</span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="51" src="https://oscimg.oschina.net/oscnet/up-74849a11a40fd8a86996d85fd09c015673c.png" width="250"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">TestComplete </span></span><span><span style="color:#494949">是用于桌面、移动和 Web 应用程序的顶级自动化测试工具,可以通过强大的记录和回放功能或使用 Python、JavaScript、VBScript 等语言编写脚本,来构建和运行功能性 UI 测试。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">TestComplete </span></span><span><span style="color:#494949">支持广泛的应用程序,如 .Net,原生或混合 iOS 、Android 应用程序,以及回归、并行和跨浏览器测试功能。使用 TestComplete,用户可以在 1500 多个真实的测试环境中扩展测试,从而改进软件质量。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fsmartbear.com%2Fproduct%2Ftestcomplete%2Ffeatures%2Fautomated-ui-testing%2F%3Futm_medium%3Dpaid_listing%26utm_source%3Dsth%26utm_campaign%3Dtop-20-automation-testing" target="_blank"><span style="color:#70b1e7">下载 30 </span><span style="color:#70b1e7">天免费试用版</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">3</span></span><span><span style="color:#494949">、 QMetry Automation Studio </span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="104" src="https://oscimg.oschina.net/oscnet/up-15f75909b19f0bea29b4a5fc5d58eef9fd2.png" width="338"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">QMetry Automation Studio (QAS)</span></span><span><span style="color:#494949">是一个领先的软件自动化工具,构建在 Eclipse IDE 和开源框架 Selenium 和 Appium 之上。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">QAS </span></span><span><span style="color:#494949">为自动化工作带来了结构、效率和可重用性。该工具支持具有编码自动化的高级自动化策略,并使手动团队能够使用无脚本自动化方法无缝过渡到自动化。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">此外,QAS 通过支持 Web、移动原生、移动 Web、Web 服务和微服务组件,为全渠道、多设备和多区域场景提供统一的解决方案。这有助于数字企业扩展自动化,从而减少对专用工具的需求。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">QAS </span></span><span><span style="color:#494949">是 QMetry 数字质量平台的一部分,该平台是最全面的软件质量平台之一,可在单个套件中提供测试管理、测试自动化和质量分析。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:免费</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fmarketplace.eclipse.org%2Fcontent%2Fqmetry-automation-studio" target="_blank"><span style="color:#70b1e7">试用 QMetry Automation Studio</span></a></span></span><span><span style="color:#494949">&nbsp;30 </span></span><span><span style="color:#494949">天。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">4</span></span><span><span style="color:#494949">、TestProject</span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="40" src="https://oscimg.oschina.net/oscnet/up-f51cbead49bbbf1e069c588274619f3937b.png" width="210"><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">TestProject </span></span><span><span style="color:#494949">是一个免费的端到端测试自动化平台,用于 Web、移动和 API 测试。同时,它也是 Gartner 评价最高的免费自动化工具,在 5 星评分制下获得了 4.6 星。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">TestProject </span></span><span><span style="color:#494949">拥有无脚本测试记录器、高级脚本 SDK(导入现有的 Selenium 和 Appium 测试)、云测试存储和页面对象存储库、200 多个社区驱动的插件以及SauceLabs、BrowserStack、Jenkins、Slack 等内置集成,因此备受工程师喜爱。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Ftestproject.io%2F%3Futm_source%3Dsoftwaretestinghelp.com%26utm_medium%3DBlog%26utm_campaign%3Dautomation-testing-tools-sth" target="_blank"><span style="color:#70b1e7">访问 TestProject </span><span style="color:#70b1e7">以创建您的永久免费帐户!</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">5</span></span><span><span style="color:#494949">、Katalon Studio</span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="60" src="https://oscimg.oschina.net/oscnet/up-524b2880e1c3fad8824dbcea42fac1c75c8.png" width="350"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Katalon Studio </span></span><span><span style="color:#494949">是一个全面的测试自动化工具,用途广泛,可在 Windows、macOS 和 Linux 上运行,涵盖从 API、Web、桌面到移动测试。它具有一套完整的功能:记录操作、创建测试用例、生成测试脚本、执行测试、报告结果,并且还可以集成在整个软件开发生命周期中的其他很多必需工具,如 JIRA、qTest、Kobiton、Git、Slack 等。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Katalon Studio </span></span><span><span style="color:#494949">的企业许可证起价为 759 美元,并为个人测试人员提供免费版本。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.katalon.com%2F" target="_blank"><span style="color:#70b1e7">访问 Katalon </span><span style="color:#70b1e7">网站</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">6</span></span><span><span style="color:#494949">、Worksoft</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="30" src="https://oscimg.oschina.net/oscnet/up-a7222eee06b5394d157d6b919febc9af33e.png" width="220"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Worksoft </span></span><span><span style="color:#494949">提供业界首屈一指的 Agile-plus-DevOps 连续自动化平台,被认为是测试 SAP 和非 SAP 企业应用程序的“黄金标准”。它为超过 250 种常用的 Web 和云应用程序提供了预构建的、开箱即用的优化,为 Web 和云应用程序提供了出色的支持。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Worksoft </span></span><span><span style="color:#494949">的优势:</span></span></span></span></p> <ul> <li><span><span style="color:#494949"><span><span>能够为打包和混合应用程序环境测试复杂的端到端业务流程</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>无代码解决方案可跨用户类型,确保为关键任务应用程序提供卓越的业务流程</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>世界领先的 SI 在其 SAP 测试实践中嵌入了 Worksoft 自动化</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>能够支持 Agile-plus-DevOps 测试实践</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>SAP Fiori 的高级对象识别功能和版本更新的快速发布</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>与其他测试工具、ALM 系统和 DevOps 工具链的开箱即用集成</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>客户的整体测试项目和维护成本平均降低了 60% 到 80%</span></span></span></span></li> </ul> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.worksoft.com%2F" target="_blank"><span style="color:#70b1e7">访问 Worksoft </span><span style="color:#70b1e7">网站</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">7</span></span><span><span style="color:#494949">、Testsigma</span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="48" src="https://oscimg.oschina.net/oscnet/up-c0cb85960e45115c90def29166137ca488d.png" width="200"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Testsigma </span></span><span><span style="color:#494949">是一款</span></span><span><span style="color:#4d5156">强大的开源测试自动化</span></span><span><span style="color:#494949">工具</span></span><span><span style="color:#4d5156">,开箱即用,让每个人都可以在几分钟内对 Web 应用程序、移动应用程序和 API 进行自动化测试,</span></span><span><span style="color:#494949">并支持云端和本地机器上的数千种设备/操作系统/浏览器组合,很好地满足了持续交付的需求。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Ftestsigma.com%2F" target="_blank"><span style="color:#70b1e7">访问 Testsigma </span><span style="color:#70b1e7">网站</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">8</span></span><span><span style="color:#494949">、ACCELQ </span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="35" src="https://oscimg.oschina.net/oscnet/up-0f523d2b665e3bddad510cc7ae6482f826e.png" width="174"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">ACCELQ </span></span><span><span style="color:#494949">是一个基于云的无代码测试自动化平台,可无缝自动化 API 和 Web 测试,实现持续测试。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">主要亮点:</span></span></span></span></p> <ul> <li><span><span style="color:#494949"><span><span>基于 AI 的测试自动化,可实现快速开发和应对变化</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>测试开发速度提高 3 倍,维护工作量降低 70%</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>无代码处理最复杂自动化的能力和灵活性</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>支持 CI/CD 与 Jira、AzureDevOps、Jenkins 等的集成</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>对 Salesforce 测试自动化以及 Salesforce 闪电和自定义对象的无缝支持</span></span></span></span></li> <li><span><span style="color:#494949"><span><span>企业技术测试自动化支持 web、api、微服务、数据库、大型机、pdf 等</span></span></span></span></li> </ul> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点解链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.accelq.com%2F%3Futm_source%3DSTL%26utm_medium%3Dcpc%26utm_campaign%3Dtop%252020%2520automation%2520tools" target="_blank"><span style="color:#70b1e7">访问 ACCELQ </span><span style="color:#70b1e7">网站</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">9</span></span><span><span style="color:#494949">、Qualibrate </span></span></span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><span><span>&nbsp;</span></span><img style='max-width:100%' height="56" src="https://oscimg.oschina.net/oscnet/up-801c6145ae02c6696d4deb1981259256b5e.png" width="195"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Qualibrate </span></span><span><span style="color:#494949">是用于 SAP 和 Web 应用测试自动化的云解决方案:它具有简单性、自定义和与大多数 CI/CD 工具集成的能力。测试用例高度可重用且易于维护。它提供了一种革命性的方法来交付软件,最大限度地降低风险,并减少高达 80% 的实施资源。</span></span></span></span><span><span>&nbsp;</span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Qualibrate </span></span><span><span style="color:#494949">的一个独特点就是业务流程记录。记录成为业务流程文档、自动化 E2E 回归测试、手动测试和最终用户培训材料的基础。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.qualibrate.com%2F%3Futm_source%3Dsoftwaretestinghelp%26utm_medium%3Dreferral%26utm_campaign%3Dawareness" target="_blank"><span style="color:#70b1e7">访问网站观看演示</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><strong><span><span><span><span style="color:#494949">10</span></span><span><span style="color:#494949">、Kobiton</span></span></span></span><span><span>&nbsp;</span></span></strong></p> <p style="margin-left:0cm; margin-right:0cm"><img style='max-width:100%' height="51" src="https://oscimg.oschina.net/oscnet/up-8148fa1c91f3507a71fe2a35834cd015b0c.png" width="137"></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">Kobiton </span></span><span><span style="color:#494949">是一个移动设备测试平台,通过在真实设备、云端或本地提供手动和自动测试来加速移动应用程序的交付和测试,支持最新的 iOS 和 Android 设备。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">它具有无脚本测试自动化能力,可以从手动测试中创建自动化测试。使用 Kobiton 创建的脚本可以在数百台设备上执行。脚本方面,支持 Appium、Selenium、XCUI、Expresso 等等。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">点击链接:</span></span><span><span style="color:#70b1e7"><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fhubs.ly%2FH0SpXSm0" target="_blank"><span style="color:#70b1e7">访问 Kobiton </span><span style="color:#70b1e7">网站</span></a></span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">以回归测试为例,飞算 SoFlu 能极大地提升效率。由于每次修改源代码时都要重复软件测试,手动修改测试不仅耗时而且成本极高。相比之下,利用飞算 SoFlu 创建自动化测试,能自动识别所有变动的接口,自动查找接口关联的所有测试用例,可以一次又一次地执行,帮助测试团队快速确定由于代码库更新而导致的问题。在自动化回归测试的帮助下,总时间可以从几天减少到几个小时。同时,回归测试自动化也可以给测试团队腾出时间,从而对生产环境中的更多异常情况进行手动探索。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm"><span><span><span><span style="color:#494949">近日,飞算 SoFlu 全自动测试平台 1.0. 4 正式发布,不仅优化了评审评论框、缺陷模版与自定义字段删除提示,还新增了邮件模版配置管理、消息通知服务管理、项目导出导入等功能。在飞算团队的持续打磨下,飞算 SoFlu 全自动测试平台以“性能优化突破业界水平+产品功能持续升级”这套组合拳,将效率提升了十倍以上。</span></span></span></span></p> <p style="margin-left:0cm; margin-right:0cm">点击链接:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.feisuanyz.com%2F" target="_blank">访问飞算SoFlu</a></p> SoFlu软件机器人 2023-05-27 https://www.v2tn.com/content/1685197809089907
真人踩过的坑,告诉你避免自动化测试新手常犯的10个错误 https://www.v2tn.com/content/1685197798079938 <p>虽然从自己的错误中学习也不错,但从别人的错误中学习总是更好的。<br> <br> 作为一个自动化测试人员,分享常见的容易犯的10个错误,可以从中吸取教训,引以为鉴。</p> <span></span> <h3>一、必要时才自动化</h3> <p>新人小王接到为Web应用程序自动化测试脚本的任务时,既高兴又紧张,因为这是他进入团队的第一个任务。第一印象至关重要,他也希望给团队留下完美的第一印象。小王被要求自动化Web应用程序其中的一个模块,但他想表现得更好、做更多的自动化,于是选择了另外的模块。然而结果是他撞进了死胡同,没有完成。其实小王想做些新尝试并没有错,错在没有咨询前辈就试图自动化该模块。事实证明,这个模块用不着自动化,因为集成的系统可能会导致多重误报。<br> <br> 我在新的自动化测试人员身上看到过很多次这种情况。毕竟,好奇心可以引领前进。当学习自动化测试时,会想尝试在每个项目中引入自动化,但这是不必要的。可能有足够的能力自动化某件事,但这件事是否足够可行?虽然众所周知自动化可以节省时间和精力,但回答以下问题非常重要:“为什么要将此项目自动化?”得到了确切务实的答案后,再为自动化开绿灯。</p> <span></span> <h3>二、定义范围</h3> <p>定义将要执行的测试的范围是非常必要的。作为新手自动化测试人员时,总是试图测试所有的东西,并使每个测试都自动化。问题是尽管可以成功地自动化所有测试,但这既不实用也不可行。</p> <p>&nbsp;</p> <p>首先,代码中有很多部分并不需要频繁的测试,但可能需要占用大量时间为其开发框架或脚本。比如当测试一个网站时,自动化网站的每个元素并在其上运行脚本是没有用的,这不值得花时间和精力。<br> <br> 其次,自动化所有的东西会增加测试自动化百分比,这会提供书面上很好的数据,让自己觉得完成了一项出色的工作,然而实际上并非如此。<br> &nbsp;</p> <p>定义测试的范围,只考虑能够及时提供实际价值的自动化测试的可行代码,做出明智选择。</p> <p><img style='max-width:100%' alt="" src="https://blog.easycorp.cn/file.php?f=easycorp/202207/f_a119e43828ca9f484608ca3c7bcc2cf0&amp;t=jpg&amp;o=&amp;s=&amp;v=1656984535"></p> <span></span> <h3>三、准确选择自动化测试工具</h3> <p>自动化测试人员最常见的另一个错误是没有选择正确的自动化测试工具。一个项目包含许多专注于不同测试目标的组件。这些目标应分为不同的工具,以帮助更有效地实现这一目标。<br> <br> 例如,如果想测试一个网站的API,最好使用Postman;但如果你想确保Web应用程序在不同浏览器间的完美呈现,那么在线Selenium Grid将是自动化跨浏览器测试的最佳选择。</p> <span></span> <h3>四、与其他测试人员良好协调</h3> <p>测试团队中有很多人,大家具备不同的技能。例如,有人可能擅长业务测试,而其他人可能擅长功能测试。然而,这不是不与他们讨论任务进展的理由。协调是加速产品交付的关键。了解谁在做什么、使用什么工具、对测试自动化的编程语言是否满意。<br> <br> 这有助于帮助排除自动化测试脚本的故障,万一事情不顺利,就会知道该寻求谁的帮助,了解团队也可以帮助自己在需要的时候进行协调。正如在最后一点中所讨论的,一个项目可能需要不同的工具来实现组合的目标,可以让擅长不同工具的测试人员发挥自己的作用。</p> <span></span> <h3>五、检查投资回报率</h3> <p>仅仅将测试人员的工资作为与整个测试过程相关的成本考虑进去是一个非常新手级的错误。显然,情况并非如此。<br> <br> 例如希望对网站执行跨浏览器测试,测试人员的工资当然是成本的一部分。但如果团队不知道这种类型的测试或与之相关的任何工具,那么还需要通过培训来提升他们的技能,这会产生额外成本。此外,还需要有合适的自动化测试工具或者框架来执行自动化浏览器测试。当然,也可以考虑开源框架。<br> <br> 这只是一个例子。同样,在对Web应用程序执行自动化测试的过程中,您还会遇到其他投资。但是,他们肯定会出现。因此,应仔细考虑测试成本,并牢记您将获得的这些投资回报。如果回报率较低,则需要更改策略并再次计算。但最终,您需要在整个测试过程中获得良好的投资回报率。</p> <span></span> <h3>六、过度依赖无代码测试</h3> <p>虽然无代码自动化测试工具的学习曲线很短,很容易入门,但它们不会帮助构建自动化测试人员配置文件所需的相关技能集。作为初学者,它们很好地帮助新手起步,但随着自身技能的发展,就会意识到它们并不像期望的那样有用。如果决定用无代码自动化工具的智慧参加自动化测试人员的面试,或者一直单独用无代码自动化来自动化复杂的web应用程序,那么将经历一段艰难的时光。<br> &nbsp;</p> <p>可靠性是这类工具的另一个大问题。在一天结束的时候,需要了解代码,以便调试自己的自动化测试套件执行出错的地方。此外,如果面对一个复杂的网站,那么就不会发现无代码自动化测试工具可以像你想的那样灵活。建议不要逃避代码,而是要熟练地学习它。最重要的是,这将是个人简历上的一大魅力。因此,作为自动化测试人员,请确保避免这种常见的错误。</p> <p><img style='max-width:100%' alt="" src="https://blog.easycorp.cn/file.php?f=easycorp/202207/f_4856f14af4402a1af703599645244473&amp;t=jpg&amp;o=&amp;s=&amp;v=1657609815"></p> <span></span> <h3>七、维护测试设计</h3> <p>测试设计是将一般测试目标转换为有形测试用例和条件的过程。作为开发人员,我们倾向于认为既然测试需要编码,为什么开发人员不能完成这项工作?如果是这样的话,那么测试这个岗位也就不存在了。<br> <br> 作为初学者,不理解测试设计的重要性可能是作为自动化测试人员最大的错误。任何时候测试任何东西都是荒谬的想法。为了有效地进行测试,测试人员需要设计测试,然后对其进行编码。设计测试有助于创建有意义的测试,并使整个测试过程非常高效。</p> <span></span> <h3>八、关注代码重用性</h3> <p>测试用例对它所应用的代码并不是唯一的。在一个项目中,会出现许多类似的组件,它们需要类似的测试设计和测试套件。比如,在使用Selenium进行跨浏览器测试时,我们发现Web页面的四个元素都是输入字段,并且需要类似的测试用例。在这里,可以通过仅为第一个元素编写测试来复制粘贴代码。虽然这将给出预期的结果,但问题是将来开发人员可能会以某种方式更改元素。现在,要更改测试用例,就需要更改所编写的每个测试套件中的代码。所有的时间都将浪费在寻找和修改这些测试代码上。<br> <br> 为了避免这种情况,应该始终关注代码的可重用性。与其一次又一次地粘贴代码,不如用适当的参数构造一个函数,并在每个元素上调用该函数。这样,如果将来有任何更改,只需要修改函数,就可以开始了。</p> <span></span> <h3>九、100%自动化是一个神话</h3> <p>跟计算机领域经典的“人月神话”一样,这里的“神话”同样指不可能达到的天方夜谭。<br> <br> 不要相信这种神话,因为作为一个自动化测试人员,这将是一个严重的错误。作为自动化测试领域的新手,对于将自动化引入到项目中都会很兴奋。但这会让人犯错误,认为自动化测试可以完全取代手动测试过程。随着时间的推移,我们将知道这是不可能的。百分之百用自动化测试取代手动测试是一个神话,它永远不可能实现。<br> <br> 作为这方面的初学者,不要试图实现这样的目标。又回到第一条,只有在必要时才进行自动化,并且只对那些需要自动化的项目进行自动化。</p> <span></span> <h3>十、遵循从头开始</h3> <p>在测试时,会遇到不同类型的问题。需要设定目标并对这些问题进行分类。一种基础方法是用较小的模块而不是大模块开始自动化测试。<br> <br> 作为自动化测试人员,最大的错误之一是开始自动化时使用更大、更复杂的模块。可能缺乏对每个用户交互中涉及的入站和出站流程的认识;甚至可能缺乏处理棘手的测试用例的熟练程度;可能最终会浪费大量的时间,但却一无所获。所以从小处开始,从基础的方法中增加自动化测试的覆盖率。<br> <br> 第一次踏入自动化测试领域,难免犯一些错误,这些错误会造成时间、金钱、精力的浪费。希望这篇文章能对自动化测试新人有所帮助,帮大家避免踩这些不必要的坑。</p> 炒蚕豆吃蹦豆 2023-05-27 https://www.v2tn.com/content/1685197798079938
如何选择合适的自动化测试工具? https://www.v2tn.com/content/1685197784935350 <p>自动化测试是高质量软件交付领域中最重要的实践之一。在今天的敏捷开发方法中,几乎任一软件开发过程都需要在开发阶段的某个时候进行自动化测试,以加速回归测试的工作。自动化测试工具可以帮助测试人员以及整个团队专注于自动化工具无法处理的各自任务,但困难的部分就是选择自动化工具。事实上,测试人员最常见的问题就是,如何选择适宜的自动化测试工具?</p> <p>在本文中,我们将详细讨论在选择自动化测试工具时如何进行选择。但在继续之前,让我们强调一下自动化测试工具的重要性。</p> <span></span> <h3>选择最佳自动化测试工具的重要性</h3> <p>如果想对项目进行成功的自动化测试,识别正确的自动化工具至关重要。为项目自动化测试选择合适的工具是获得项目所需结果的最佳方法之一。让我们以web应用程序开发为例,更好地了解自动化测试工具的重要性。</p> <p>假设您正在为业务开发一个网站。现在,在一开始,如果你是在低水平上创业,你不需要任何自动化测试。所有测试都可以用手动方法完成。但是,当您的业务开始增长并开始获得广泛受众的认可时,您可能需要自动化一些流程,如web应用的跨浏览器测试,以确保它为所有用户提供类似的体验。</p> <p>假设正开发一个网站。如果初期是处在较低水平,那不需要任何自动化测试,所有的测试都可以用手工方法完成。但是当业务开始增长,并广泛获得用户的认可时,就可能需要自动化一些流程,如跨浏览器测试这个web应用,以确保它为所有用户提供类似的体验。</p> <p>此外,如果需要回归测试,那么也需要执行自动化测试。这就是为何选择一个能够提供所有这些功能的自动化工具是必要的。</p> <span></span> <h3>自动化测试工具的种类</h3> <p>通常有三种类型的自动化测试工具可供选择。以下是每种类型的简要说明:</p> <span></span> <h4>1.&nbsp;开源自动化测试工具</h4> <p>开源工具基本上是免费的平台,允许您访问和使用源代码,也可以修改其原始设计。使用开源工具没有任何成本或费用。</p> <p>此外,开源工具可以用于测试过程的任何阶段,如测试用例管理、bug跟踪、调试等。当然,一般来说,与商业测试工具相比,开源自动化工具的功能更少。</p> <span></span> <h4>2.&nbsp;商业自动化测试工具</h4> <p>商业测试工具是专门为商业目的而设计和生产的。诸多大型企业会选择使用商业自动化测试工具,因为它们具有可扩展特性和来自技术团队的支持。</p> <span></span> <h4>3.定制工具或自研工具</h4> <p>对于小众测试项目,测试环境和测试过程有一些特殊的特征,这是开源或商业自动化测试工具无法实现的。因此,测试主管需要考虑定制工具的开发。这些类型的工具很少被少数组织使用,因为它们需要明确地开发。</p> <span></span> <h3>选择自动化测试工具时要考虑的因素</h3> <p>选择正确的自动化测试设置取决于多个因素。每一个测试设置在开始时独一无二,随着项目的发展可能演变成完全新颖的东西。选择将随着项目规模而扩大的正确设置与选择用于开发应用程序的正确技术堆栈同等重要。以下是影响决策的几个因素:</p> <ul> <li>该工具是否支持您的测试活动,以及是否在市场上可用。</li> <li>哪个自动化测试工具最适合您的项目需求和预算。</li> <li>团队是否具备使用该工具所需的技能,如果没有,那么在您购买测试工具后,谁将使用该工具。</li> <li>自动化工具对于您正在使用的项目环境和技术是否准确。</li> <li>该工具是否有免费试用版,以便购买前分析其性能。</li> <li>随着项目的增长,扩展测试平台所涉及的成本和开发工作是什么。</li> <li>维护和管理旧的测试以在项目中使用更新有多困难。</li> </ul> <p>尽管在选择自动化工具时包含许多因素,但我们相信这些是您在寻找自动化测试工具之前需要考虑的基本因素。让我们更深入地探讨选择最佳自动化测试工具的概念。</p> <span></span> <h3>自动化测试工具的选择标准</h3> <p>无论您的项目对自动化测试工具有什么要求,总是有一种简单而有效的方法来为您的项目选择最佳的自动化测试工具。</p> <span></span> <h4>1.全面分析项目需求</h4> <p>通过提供无缺陷的产品来保持项目的质量对于项目的成功至关重要。自动化测试是提高任何项目质量以及增加测试深度和范围的最佳方法。但是,在实施自动化测试之前,请清楚地了解您的项目需求,例如:</p> <ul> <li>项目类型是什么?它是web/桌面/移动应用程序还是其他类型项目?</li> <li>项目发布后的范围是什么?</li> <li>在流程开始之前,分析测试团队在代码语言方面的实力。</li> </ul> <p>一般来说,没有完全好或坏的自动化工具,但是如果希望该工具具有良好的ROI,这完全取决于项目需要,例如实际需要自动化什么以及有多少测试用例需要自动化测试。</p> <p>对于大多数项目,普遍认为手动和自动化测试对于web、移动和桌面应用程序的测试都是必不可少的。因此,可以选择能够与项目规划和测试管理工具无缝集成,而且学习速度快、使用方便的工具。</p> <p>&nbsp;<img style='max-width:100%' alt="" src="https://blog.easycorp.cn/file.php?f=easycorp/202206/f_e62ef158cca77303840d88008edc9cf1&amp;t=jpg&amp;o=&amp;s=&amp;v=1654758155"></p> <span></span> <h4>2.将现有的自动化工具作为基准进行比较</h4> <p>如果您正在使用像Selenium测试自动化这样的开源自动化工具,那么可以将其作为评估和确定项目最佳自动化测试工具的基准。为此,就需要了解Selenium自动化工具的优点和缺点。</p> <p><img style='max-width:100%' align="" alt="" height="218" src="https://blog.easycorp.cn/file.php?f=easycorp/202206/f_4582b922ba5d2682b0ba772d5400fe02&amp;t=jpg&amp;o=&amp;s=&amp;v=1655867449" width="500"></p> <p>&nbsp;</p> <p>&nbsp;</p> <p>例如,Selenium是一种开源的免费工具,允许用户测试其web应用程序和网站。它还为自动化测试提供了独特的功能,如记录回放以创建记录回放测试脚本,以及对多种语言的语言支持。但是,Selenium WebDriver并不能提供良好的客户支持。</p> <p>Selenium是熟悉编码技术并通过用户界面测试其网站的测试人员的首选。此外,Selenium套件的维护并不容易,尤其是对于经常监督手动和自动化测试的测试人员来说。使用Selenium可能面临的另一个挑战是web应用的浏览器兼容性测试,因为不可能跨浏览器、操作系统和设备的多种组合自动进行跨浏览器测试。</p> <p>因此,选择当前的测试工具作为基准并将其与决定购买用于自动化测试的工具进行比较是至关重要的。</p> <span></span> <h4>3.验证适合项目的关键标准</h4> <p>在确定项目的最佳自动化工具之前,需要考虑以下要点:</p> <ul> <li>对于任何项目成员来说,测试执行都必须简单,以便成员都能够在需要时高效地运行测试。此外,对于技术知识很少的非技术用户来说,这也应该是容易的。</li> <li>该工具生成的测试报告对于管理团队来说必须直观、简单,以便他们能够理解测试过程。</li> <li>自动化测试工具必须支持所有三种平台,包括web、桌面和移动应用程序。</li> <li>测试脚本的开发和维护必须减少人力和时间资源管理。</li> <li>当涉及到web应用程序的跨浏览器测试时,自动化工具必须支持多种浏览器和平台。</li> <li>支持关键字驱动测试,因为它充当了数据驱动测试框架的扩展。</li> <li>自动化工具必须支持项目所需的语言,以便测试人员可以轻松地编写代码。</li> <li>在选择自动化测试工具时,技术支持和协助是首要任务,请确保该工具可以获得持续的技术支持。</li> <li>如果包含其他功能是加分项,如屏幕截图测试、视觉外观测试、实时测试等。</li> </ul> <p>比较不同自动化工具的这些关键因素,然后从中选择最佳因素。</p> <span></span> <h4>4.在购买工具前考虑预算</h4> <p>在根据上述标准比较了不同的自动化工具之后,最后要确认预算。预算是关键的问题之一,这个最好理解,不管根据上述选的工具如何满意,超过组织预算的话都无法实现。</p> <p>如果组织已最终确定购买该工具,则建议下载并使用该工具的试用版,以分析其性能,以及是否值得投入这么多资金。在试用之后,如果发现该工具有任何问题,那么不要花太多时间在它上面,而是寻找另一个自动化测试工具。只有确定工具的功能和性能时,才购买该工具。</p> 炒蚕豆吃蹦豆 2023-05-27 https://www.v2tn.com/content/1685197784935350
全栈代码测试覆盖率及用例发现系统的建设和实践 https://www.v2tn.com/content/1685197765037926 <blockquote> <p><strong>本文首发于微信公众号 “<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fmp.weixin.qq.com%2Fs%2FiyBVEv8FOrytydFLe5sEyQ" target="_blank" rel="nofollow">Shopee 技术团队</a>”</strong></p> </blockquote> <span></span> <h1>1. 背景</h1> <p>随着项目不断深入迭代,业务逻辑以及用户场景日渐复杂,补充和维护单元测试维护的成本也变得越来越高。测试覆盖质量通过测试用例评审或者人工 Code Review 的方式费时费力,单凭多方沟通和经验累积的方法,往往不够准确,也难以避免开发人员存在在代码上线前“夹带私货”的场景,并且没有量化的、直观的客观数据来支撑。</p> <p>为了在有限的时间及人力成本内保证项目质量,实现对项目质量的精细化管理,我们研发了 <strong>Finder —— 全栈代码测试覆盖率及用例发现系统</strong>(下文简称 Finder),通过精确化的数据量化代码质量,从而实现精准化测试。本文将介绍 Finder 的总体架构,以及它作为质量保障体系中的重要一环,如何在项目中实现精确化测试。</p> <span></span> <h1>2. Finder 项目介绍</h1> <p>Finder 主要分为两个模块,一个是<strong>测试过程中对代码测试覆盖率进行收集与统计</strong>,一个是<strong>分析代码和用例的映射关系,精准确定回归测试范围</strong>。</p> <p><img style='max-width:100%' alt="" height="392" src="https://oscimg.oschina.net/oscnet/up-c74f9c739d2af76c7c0fe9b793753022ef2.png" width="700"></p> <p><strong>代码测试覆盖率统计模块</strong>,能够满足多环境、多需求、多服务的复杂测试场景,实时收集测试过程中的覆盖率信息,并生成覆盖率统计报告;其支持多端语言接入(Web、React Native、Golang),实现前后端项目全覆盖,打通整体研发流程。</p> <p><img style='max-width:100%' alt="" height="423" src="https://oscimg.oschina.net/oscnet/up-ddb4ce295ec29cb7f3ccd74ea3018f70c69.png" width="700"></p> <p><strong>相关用例发现模块</strong>,针对变动的代码分析函数调用关系,追溯完整的调用关系链路,标记出所影响的 API 接口及相关用例,确定测试回归范围。</p> <span></span> <h1>3. 架构设计</h1> <p><img style='max-width:100%' alt="" height="360" src="https://oscimg.oschina.net/oscnet/up-46fad42c3351f09cda50b143f2e3424adb8.png" width="700"></p> <p>Finder 分为代理层、应用层、核心服务层三个模块:</p> <ul> <li><strong>代理层 Finder Agent</strong>,负责前期数据采集的工作,包括编译阶段的代码插桩、覆盖率数据的采集、解析源码函数调用关系信息等;</li> <li><strong>应用层 Finder Platform</strong>,包含需求信息管理、分支信息管理、单文件覆盖率染色图展示、API 信息展示、测试用例关联、函数调用链展示等页面模块;</li> <li><strong>核心服务层 Finder Server</strong>,其中,覆盖率分析和服务调用分析是最主要的两个模块: <ul> <li><strong>覆盖率分析</strong>,对收集到的覆盖率数据进行数据聚合、差异增量分析、数据修正等操作;</li> <li><strong>服务调用分析</strong>,将源码解析工具传输来的数据进行数据结构转换后,完成调用拓扑图生成、API 信息关联、测试用例发现等操作。</li> </ul> </li> </ul> <p>在前期完成数据采集的接入工作后,测试人员无需额外操作,正常进行业务测试,测试完成后可以在可视化平台中查看覆盖率数据、相关测试用例等信息。</p> <span></span> <h1>4. 实现方案</h1> <span></span> <h2>4.1 代码测试覆盖率模块</h2> <p><img style='max-width:100%' alt="" height="607" src="https://oscimg.oschina.net/oscnet/up-d836734717d5f2dce05c54d02937f0da56d.png" width="700"></p> <p>代码覆盖率模块主要分为两个步骤,<strong>第一步是通过对项目源码插桩,采集覆盖率信息;第二步是对覆盖率信息进行分析,通过可视化平台展示统计报告</strong>。</p> <span></span> <h3>步骤一:插桩与数据采集</h3> <p>代码插桩,意为在程序中插入一些代码,用于跟踪被测程序的某些信息。对于覆盖率测试而言,插桩的目的是检测程序中可执行语句被执行(即被覆盖)的情况。</p> <p>Finder 支持 JS 和 Golang 两种程序语言的代码覆盖率统计,接入成本低,对业务需求无侵入性。</p> <ul> <li>对于 JS 程序,我们在 babel 编译阶段进行插桩操作,注入到全局对象 window 中。我们提供了上报覆盖率数据的 npm 包 —— coverage-report,前端应用接入后会主动上报数据到 Finder Server;</li> <li>Golang 程序的覆盖率接入对业务项目零侵入,只需要引入 Finder Agent —— 覆盖率收集工具:它在编译阶段对源码插桩,包括 Git 信息和覆盖率信息注入;插桩完成后的服务会启动一个统计覆盖率的 Http Server,Finder Server 通过该 Http Server 提供的接口定时请求覆盖率数据。</li> </ul> <span></span> <h3>步骤二:差异覆盖率统计</h3> <p>比起全量代码的覆盖率,实际上我们更关心改动代码部分的覆盖率情况。可以通过 Git 指令对比功能分支与 master 分支的代码差异,过滤无关代码,只针对改动代码部分进行覆盖率统计。</p> <p><strong>为实现差异覆盖率的计算,我们约定以行(line)作为维度的结构表示 Git 代码差异和覆盖率信息,满足两者一一对应的关系。</strong></p> <p><img style='max-width:100%' alt="" height="382" src="https://oscimg.oschina.net/oscnet/up-92721c1bef57748a797c0df61a29667815e.png" width="700"></p> <p>首先将 Git 分支对比得到的 Diff 数据转换成以代码行作为索引的数组格式,<strong>元素的值有空值和 + 两种枚举值</strong>:</p> <ul> <li>空值代表没有改动;</li> <li>+ 代表有改动。</li> </ul> <p>覆盖率数组也转换成以代码行作为索引的数组格式,元素的值有 -1、0、1 三种枚举值:</p> <ul> <li>-1 代表无需统计覆盖率的代码(例如空格,注释等);</li> <li>0 代表未覆盖的代码(尚未执行);</li> <li>1 代表已覆盖的代码(已被执行)。</li> </ul> <p>将 Diff 数据与覆盖率数组进行合并,将非改动代码的覆盖率值置为 -1 。得到最终的差异覆盖率数据。</p> <p><img style='max-width:100%' alt="" height="594" src="https://oscimg.oschina.net/oscnet/up-54140412b05403f60adf667f68731f234ec.png" width="700"></p> <span></span> <h3>关键问题一:数据源标准化</h3> <p>由于不同程序语言上报的覆盖率数据结构都不一致,我们需要将数据源标准化,<strong>统一转化以行(line)为维度的数组结构</strong>。</p> <p>首先,前端应用上报的覆盖率数据包含三种维度的覆盖率数据:</p> <ul> <li>Statement Coverage:语句维度的覆盖率数据;</li> <li>Branch Coverage:条件维度的覆盖率数据,例如 if/else、switch、三元运算符等;</li> <li>Function Coverage:函数维度的覆盖率数据。</li> </ul> <p>对于这三类覆盖率,我们做出以下数据转换:</p> <p><img style='max-width:100%' alt="" height="309" src="https://oscimg.oschina.net/oscnet/up-80d185151276310f547d69a9f756ae28eca.png" width="700"></p> <p>我们<strong>采用与操作</strong>将三类覆盖率数据合并为行覆盖率,即一行代码满足三类覆盖率才算被执行过。</p> <p>而后端 Golang 服务采集的覆盖率数据,如下图。</p> <p><img style='max-width:100%' alt="" height="181" src="https://oscimg.oschina.net/oscnet/up-e0621d914ee5bb6950538d8bc6f81cfe45a.png" width="700"></p> <p>同样,我们也需要将其转换为行维度的数组结构。</p> <p><img style='max-width:100%' alt="" height="412" src="https://oscimg.oschina.net/oscnet/up-3ca7d001e2c6c9923655055ddf1296ea011.png" width="700"></p> <span></span> <h3>关键问题二:确保代码变更后的覆盖率正确性</h3> <p>在集成测试的过程中,开发人员不可避免地会进行代码更新。当代码更新后,我们希望能够记录新代码改动覆盖率的同时,依然保持原有代码的覆盖率数据。所以我们需要获取新旧提交之间的代码差异,对原有覆盖率数据进行“修正”操作:</p> <p><strong>对原有的覆盖率数据,先删除 diff 结果中被移除的代码对应的覆盖率数据,再插入 diff 结果中新增的代码对应的覆盖率数据。</strong></p> <p>举个例子:</p> <p><img style='max-width:100%' alt="" height="223" src="https://oscimg.oschina.net/oscnet/up-281b24777992c3952d52d07c6cd392c1ae9.png" width="700"></p> <p>对比首次提交 commit 1 和 master 分支,得到首次改动:新增三行代码。</p> <p>标记这三行代码的行索引 3、4、8,并统计它们的覆盖率。</p> <p><img style='max-width:100%' alt="" height="253" src="https://oscimg.oschina.net/oscnet/up-c1b01161df4d30f03d32139fb1e63f0c8fb.png" width="700"></p> <p>对比 commit 1 和 commit 2,得到两次提交之间的改动:删除之前两行代码,新增一行代码。</p> <p>移除原数据中第 3、4 行数据,然后插入新改动代码的行索引 7(删除后的索引位置)并统计新改动的覆盖率。</p> <p><img style='max-width:100%' alt="" height="215" src="https://oscimg.oschina.net/oscnet/up-3d75966637c2b1ea149423cf3b1d4bbdba1.png" width="700"></p> <p>修正后的结果和 commit 2 与 master 分支对比的结果一致,既保留了首次改动的覆盖率数据,也记录了新改动的覆盖率数据。</p> <span></span> <h3>关键问题三:单环境的代码覆盖率采集</h3> <p>在实际开发流程中,研发环境只有一套,我们往往不能独占它,所有周版本需求都在 staging 环境开发,在 test 环境测试。这样会出现一个问题:由于这种单一环境的测试流程,导致统计出来的覆盖率无法区分来自哪个具体功能分支,进而影响对各功能需求的测试范围判断。</p> <p>为了解决这个问题,我们提出两个方案:</p> <p>第一个方案是搭建多泳道研发环境,通过 PFB(Per Feature Branch)的形式对各需求开发环境进行隔离。PFB 是一个可以快速搭建虚拟环境的工具。它支持将多个功能分支版本同时部署在同一个测试环境中,且每个功能分支可拥有单独的流量访问,从而实现不同的功能分支可拥有相对隔离的虚拟环境。</p> <p>但是由于这个架构改动较大,距离落地到项目中还需一段时间,因此第二个方案应运而生:我们<strong>对单一的集成分支进行功能追溯,判别出变动代码是属于合并进来的哪一个功能分支,并进行分类展示</strong>。</p> <p><img style='max-width:100%' alt="" height="222" src="https://oscimg.oschina.net/oscnet/up-327c9b43ae3a22fb441f2e16703d1448b83.png" width="700"></p> <ul> <li>通过 Git Blame 命令从集成分支中判别出到各行代码对应的 commit hash;</li> <li>通过 Git Branch 命令查找 commit hash 来自哪一个功能分支。</li> </ul> <p>通过以上两步寻找到每行代码与功能分支的对应关系,与覆盖率结果进行映射后可得出对单一集成分支的功能追溯效果,解决单环境的代码覆盖率采集问题。</p> <span></span> <h2>4.2 相关用例发现模块</h2> <p>相关用例发现模块的关键是通过追溯变动代码的调用关系链,确定测试回归范围。这个过程主要分为两个阶段:<strong>源码解析阶段</strong>和<strong>数据分析阶段</strong>。</p> <p><img style='max-width:100%' alt="" height="626" src="https://oscimg.oschina.net/oscnet/up-65532cfdd4f529500eb3f7c63026738bdc0.png" width="700"></p> <span></span> <h3>步骤一:源码解析</h3> <p>我们在 Gitlab CI 接入源码解析工具,当有新代码提交时,触发源码解析。</p> <p>通过对抽象语法树 AST 和中间转换代码 SSA 进行解析,得到以下数据:</p> <ul> <li>项目 Git 信息</li> <li>函数基本信息</li> <li>函数调用关系</li> <li>RPC 调用信息</li> <li>API 信息</li> </ul> <p>最后将这些数据都打包统一发送到 Finder 服务端。</p> <span></span> <h3>步骤二:数据分析</h3> <p>Finder 服务端接收到解析数据后,进行差异增量代码的函数调用关系全链路追溯,最后标记出相关的 API 信息及测试用例。具体追溯流程如下:</p> <p><img style='max-width:100%' alt="" height="303" src="https://oscimg.oschina.net/oscnet/up-e8a9b32bf9ceeba7303a5a2d37750cf4a5c.png" width="700"></p> <ol> <li>Git Diff 得到功能分支与 Master 分支对比的代码改动;</li> <li>通过差异增量代码的所在行数,确定所属函数体,进入步骤 3;</li> <li>追溯指定函数的调用关系,直到寻找到 API 触发函数;</li> <li>若遇到 RPC 调用的情况,进行 RPC 调用关系追溯,找到 RPC 调用方函数,继续回到步骤 3 的操作;</li> <li>追溯工作完成,得到从变动函数到 API 触发函数的调用关系全链路;</li> <li>通过以上得到的 API 触发函数,标记相关的 API 信息及测试用例。</li> </ol> <p>每次代码变更都会触发上述流程,得到最新的函数调用链路信息,在可视化前台中展示该功能分支的变动函数调用关系链,以及相关测试用例。</p> <span></span> <h3>关键问题:后端微服务架构串联,全链路覆盖</h3> <p>目前我们后端服务采用了分布式的微服务架构,例如一个购买商品的流程,当用户进入 APP 浏览商品时,会发起请求经过网关层,转发到商品服务,然后在创建订单时会调起订单服务,订单服务再调用用户信息服务和促销服务,整个过程还会调用多个基础服务共同完成一次操作流程。</p> <p>我们希望除了解析服务内的调用关系外,也需要服务间的调用关系串联起来,得到完整的调用链路。</p> <p><img style='max-width:100%' alt="" height="222" src="https://oscimg.oschina.net/oscnet/up-3e375a1e23d4a21cef503069577cb325fa5.png" width="700"></p> <p>为了解决这个问题,<strong>我们针对项目中的 RPC 调用关系进行静态解析</strong>,通过寻找调用方函数——RPC Command——被调用方函数三者的关联关系,对调用方函数和被调用方函数进行标记,当函数调用关系链追溯到被调用方函数时,匹配到其对应的调用方函数,继续向上追溯,从而得到服务间的完整调用关系链路。</p> <span></span> <h1>5. 实践应用</h1> <p>Finder 通过接入团队中的项目流程管理系统,在整个需求生命周期的各个环节发挥着不同的作用。</p> <p><img style='max-width:100%' alt="" height="254" src="https://oscimg.oschina.net/oscnet/up-9793a926bffeeacb85fa47edc78a5be7091.png" width="700"></p> <span></span> <h2>5.1 提测阶段</h2> <span></span> <h3>5.1.1 覆盖率提测达标</h3> <p>开发人员必须达到规定的覆盖率标准才能提测,对于覆盖率未达标的情况,开发人员需要反推代码逻辑是否存在问题,进一步分析前期技术方案设计不够合理,还是对技术方案的实现有误,或者是在实现过程中造成的策略性放弃等。</p> <span></span> <h3>5.1.2 覆盖率定制化</h3> <p>针对不同项目会有定制化的覆盖率要求,支持配置需要忽略统计覆盖率的文件类型以及目录。</p> <p>对于移动端应用,提供 iOS 和 Android 双平台的覆盖率数据统计,这样能够提前暴露移动端的兼容性问题,保证提测交付质量。</p> <p><img style='max-width:100%' alt="" height="172" src="https://oscimg.oschina.net/oscnet/up-6cceecc49b1ee353eae0f8fc47e5ada8b28.png" width="700"></p> <span></span> <h2>5.2 测试阶段</h2> <span></span> <h3>5.2.1 覆盖率实时分析</h3> <p>测试人员介入测试后可以在 Finder 平台上实时查看覆盖率分析结果,了解该测试版本变更代码的测试覆盖情况。</p> <p><img style='max-width:100%' alt="" height="247" src="https://oscimg.oschina.net/oscnet/up-cba510b8ea1076e79c9ed5a4b6fcb580d43.png" width="700"></p> <span></span> <h3>5.2.2 覆盖率染色图</h3> <p>通过代码覆盖率染色图辅助整个测试过程,方便测试人员对测试用例进行查漏补缺,尽可能保证所有关键场景都能覆盖到;同时可以驱动测试人员加强对代码的理解,充分把控代码质量。</p> <p><img style='max-width:100%' alt="" height="172" src="https://oscimg.oschina.net/oscnet/up-88f56eb866d0503b0f7d81b0a61170d4bc1.png" width="700"></p> <span></span> <h3>5.2.3 需求维度覆盖率统计</h3> <p>通过关联项目管理系统,从需求级别的角度,提供该需求下各模块的覆盖率数据,包括不同的后端服务和前端应用,辅助测试人员做决策,衡量质量风险。</p> <p><img style='max-width:100%' alt="" height="230" src="https://oscimg.oschina.net/oscnet/up-3b4ed69f889cf77ab72fe95d4185585a1f8.png" width="700"></p> <span></span> <h2>5.3 回归阶段</h2> <span></span> <h3>标记变更范围</h3> <p>根据<strong>代码变更范围</strong>推断出<strong>函数变更范围</strong>,进一步标记出相关测试用例,从而实现用例和代码的关联关系。</p> <p>用例发现分析报告中会标记出该需求变更部分的相关信息,包括<strong>变更的函数调用关系链路和受影响的 API 接口</strong>,测试人员从中可以快速确定回归测试范围,通过更小的维度更精准地度量测试质量,针对性进行自动化/手工测试,极大减少回归阶段的工作量,以较小的回归成本保证较高的测试质量。</p> <p><img style='max-width:100%' alt="" height="156" src="https://oscimg.oschina.net/oscnet/up-769076144f45a35970d5595ad36286dff4c.png" width="700"></p> <p><img style='max-width:100%' alt="" height="87" src="https://oscimg.oschina.net/oscnet/up-c55f59de1586bb3e17b4cbb1d781d222944.png" width="700"></p> <span></span> <h1>6. 未来展望</h1> <p>Finder 作为项目中质量保障体系中的一环,目前还处于初级阶段。在未来我们会持续寻找 Finder 在研测协同体系中的更优实践。</p> <p><strong>1)支持更多维度的覆盖率数据统计</strong></p> <p>我们希望在统计方面可以提供更产品化更精细化的数据,包括关键字覆盖率、相关代码覆盖率、高风险覆盖率等,能够更好地辅助测试人员做决策。</p> <p><strong>2)精准记录 Bug 轨迹</strong></p> <p>后续我们打算支持通过以添加标记的形式单独统计覆盖率,通过记录 bug 的完整代码轨迹,还原问题的复现路径,精确定位问题所在。</p> <p><strong>3)建立用例知识库</strong></p> <p>构建用例与代码映射关系,形成用例知识库,支持对代码和用例进行关联管理,精确推荐改动代码关联的用例,提供测试用例优化建议。</p> <blockquote> <p><strong>本文作者</strong></p> <p>Hao、Qianguang,前端工程师,来自 Shopee Digital Purchase 团队。</p> </blockquote> Shopee技术团队 2023-05-27 https://www.v2tn.com/content/1685197765037926
代码历史上最昂贵的 7 个错误 https://www.v2tn.com/content/168519775360563 <p>算法或程序中的一个小技术错误就可能造成数百万美元的损失。本文带大家看看迄今为止历史上因程序错误而带来后果最为昂贵的 7 个错误。</p> <span></span> <h3>美国宇航局火星气候轨道器:1.93 亿美元</h3> <p>1999年,美国宇航局的火星气候轨道飞行器进入了一个过低的轨道,导致航天器在大气层中燃烧。这一失败最终追溯至一次换算错误——英制磅秒单位没有转换成标准公制牛顿秒。<br> <br> 美国宇航局的火星轨道器是其火星勘测者计划中的第二个探测器,其中还包括 1996 年 11 月发射的火星全球勘测者和 1999 年 1 月发射的火星极地着陆器。 它们被设计成大致同时到达,对火星的表面、气候和大气进行实验。它原定于 1999 年 9 月 23 日到达轨道。美国宇航局的科学家们希望,一旦航天器到达火星,它将帮助他们重建气候历史,并在地表找到水的迹象。本次任务结束后,它还将作为未来火星任务的通信中继。<br> <br> 1999年9月23日,火星气候轨道器按计划开始入轨燃烧。飞船原定在经过火星后重新建立联系,然后发送信号,但不幸的是,飞船没有收到任何信号。 在TCM-4及进入轨道的一个礼拜间,导航团队认为探测器的高度有可能比预期的还要低得多,大约位于150至170公里。<br> <br> 火星气候探测者号任务失败的主要原因是人为因素,因为火星气候探测者号上的飞行系统软件使用英制单位磅力计算推进器动力,而地面人员输入的方向校正量和推进器参数则使用公制单位牛顿,导致探测器进入大气层的高度有误,最终瓦解碎裂。<br> &nbsp;</p> <span></span> <h3>水手 1号:1850 万美元</h3> <p>水手1号事件,也被称为人类历史上最昂贵的连字符,是美国宇航局的另一个失误,虽然很小,但导致公司损失了数百万美元。<br> <br> 水手号的计划中发射了一系列为探索火星、金星、水星等而设计的无人太空船。这个计划夺得多项第一,包括:第一次跨星系星际飞越、第一个行星探测器以及第一个以重力加速航行的太空船。<br> <br> 水手 1 号于 1962 年 7 月 22 日上午 9 点 21 分发射,距离发射不到 5 分钟,任务被迫中止;人类历史上最具历史意义的一次飞行坠毁于地面,而这只是因为数学代码中的一个小错误。<br> <br> 美国宇航局在其网站上引述道:“靶场安全官检测到计划外的偏航提升动作之前,助推器的表现都是让人满意。但引导命令的错误应用导致无法转向,并将导致航天器坠毁,可能坠毁于北大西洋航道或有人居住的区域,因而‘一名靶场安全官随后下令进行破坏性中止’。”<br> <br> 事故发生几天后,《纽约时报》发表了一篇文章,解释了坠机的原因。它说这个错误是“在一些数学数据中遗漏了一个连字符”的结果。据称,美国宇航局的一名程序员在将“大量编码信息”输入计算机系统时遗漏了这个符号。<br> <br> 几天后,美国宇航局官员理查德·莫里森向国会提交了销毁火箭的案例,并强调了微小遗漏的重要性:“连字符提示航天器在恢复雷达联系前,需忽略计算机提供的数据。当该连字符被省略时,虚假信息被输入航天器控制系统。在这种情况下,计算机将火箭向左转,机头朝下,火箭服从该命令并坠毁。”</p> <span></span> <h3>阿丽亚娜 5 号航班 501:800 万美元</h3> <p>1996 年 6 月 4 日,欧洲航天局发射的无人驾驶的阿丽亚娜 5 号火箭在从法属圭亚那库鲁升空仅 40 秒后爆炸。这枚火箭在耗资数百万美元的开发十年后开始了它的第一次航行。<br> <br> 调查委员会调查了爆炸的原因,并在两周内发布了一份报告。原来,失败的原因是惯性参考系统中的软件错误。阿丽亚娜 5 上安装的软件最初是为 阿丽亚娜 4 开发的。阿丽亚娜 5 有一个更强大的引擎,这导致了以前版本不可能出现的错误。<br> <br> 与火箭相对于平台的水平速度相关的64位浮点数被转换为16位有符号整数。该数字大于这是可存储在16位有符号整数中的最大整数32767,因此转换失败。因此,在第39秒,火箭在空气动力的作用下开始崩溃和自毁。</p> <span></span> <h3>奔腾处理器漏洞:4.75 亿美元</h3> <p>Pentium FDIV 漏洞是最著名、或者说是最臭名昭著的英特尔微处理器漏洞。它旨在变得更快、更准确,但结果却被窃听并导致作为英特尔 SRT 算法一部分的查找表出现错误。<br> <br> 为了将浮点标量代码的执行速度提高 3 倍,向量代码的执行速度提高 5 倍,与 486DX 芯片相比,英特尔决定使用 SRT 算法,该算法可以在每个时钟周期生成两个商位,而传统的 486 移位和减法算法每个周期仅生成一个商位。此 SRT 算法使用查找表来计算浮点除法所需的中间商。Intel 的查找表由 1066 个表条目组成,其中由于编程错误,有五个没有下载到可编程逻辑阵列 (PLA) 中。当浮点单元 (FPU) 访问这五个单元中的任何一个时,它 (FPU) 取零而不是 +2,这应该包含在“缺失”单元中。<br> <br> 在最坏的情况下,此错误的发生率可能高达十进制数的第四位有效数字,但发生这种情况的可能性为 3600 亿分之一。错误出现在第 9 位或第 10 位十进制数字中是最常见的,这种情况发生的几率为 90 亿分之一。然而,心怀不满的客户认为每个用户都应该得到正常工作的硬件并要求更换。</p> <span></span> <h3>莫里斯蠕虫:1 亿美元</h3> <p>如果说一个试图解决问题的学生不小心创建了恶意软件,导致价值 1 亿美元的损失来弥补损失,你会相信吗?可确实如此,这正是 1988 年 11 月 2 日发生的事情。康奈尔大学的研究生罗伯特·泰潘·莫里斯不小心创建了一个恶意软件程序。起初,它是程序中的一个无害实验,但代码中有一个小错误。该恶意软件开始迅速传播,随后摧毁了数千台计算机。<br> <br> 罗伯特莫里斯被指控犯有网络犯罪,并因此被罚款 10000 美元。然而,恶意软件总共导致了 1 亿美元的花费来修复受影响的计算机。<br> <br> 莫里斯的律师声称,该蠕虫有助于提高网络安全,因为它有助于开发防病毒软件,并在未来让用户意识到此类恶意软件。后来,莫里斯成为了 Y Combinator 的联合创始人。他是麻省理工学院的副教授。带有恶意软件源代码的软盘存储在波士顿大学。让我们只希望它不会变异。<br> <br> 而比事件影响更大、更深远的是:黑客从此真正变黑,黑客伦理失去约束,黑客传统开始中断。大众对黑客的印象永远不可能回复。而且,计算机病毒从此步入主流。</p> <span></span> <h3>Knight 破产:4.4 亿美元</h3> <p>如果美国股票市场的一个关键利益相关者开始以高价买入,以低价卖出,会怎么样?听起来不是一个好的贸易策略,对吧?这正是发生在奈特身上的事情,差点导致他们破产。<br> <br> 2012年8月1日上午,发生了一件任何一位CEO都会做的噩梦。花了17年时间才建成的建筑在几个小时内几乎倒塌。一些新的交易软件中有一个bug,只有在纽约证券交易所当天开市时才被激活。这个错误的软件让Knight掀起了一场收购狂潮,很快,该公司就在交易的第一个小时内购买了约150家不同公司的股票,价值约70亿美元。<br> <br> 2012 年 8 月 1 日上午,发生了对任何一位 CEO 都是噩梦的事情:花了 17 年的时间建造的东西几乎在几个小时内就崩溃了。一些新的交易软件有一个bug,该bug在当天纽约证券交易所开盘时才被激活。这个错误的软件让Knight掀起了一场收购狂潮,很快,该公司就在交易的第一个小时内购买了约150家不同公司的股票,价值约70亿美元。<br> <br> Knight 试图取消交易,但美国证券交易委员会 (SEC) 主席 Mary Schapiro 拒绝了。除六支股票的交易被撤销,Knight的其他购买狂潮并未达到取消门槛——使所购股票的价格上涨超过 30%。在其他情况下,交易成立。<br> <br> 这对Knight来说是个坏消息,一旦明确交易会成立,Knight别无选择,只能抛售它购买的股票。就像早上的疯狂购买推高了这些股票的价格一样,大规模的市场抛售很可能会迫使价格下跌,可能会跌至Knight无法弥补损失的地步。<br> <br> 高盛(Goldman Sachs)介入,以花费Knight4.4亿美元的价格收购了Knight不想要的全部头寸。</p> <span></span> <h3>千年虫:5000 亿美元</h3> <p>一位数能带来什么危害?早在 1999 年,它就耗资 5000 亿美元。Y2K 错误,也称为千禧年错误,是一种计算机缺陷。由于其中的年份只使用两位十进制数来表示,因此当系统进行跨世纪的日期处理运算时(如1999 年 12 月 31 日之后的日期),就会出现错误的结果,进而引发各种各样的系统功能紊乱甚至崩溃。<br> <br> 在 1960 年代到 1980 年代编写复杂的计算机程序时,计算机工程师使用两位数的代码来表示年份。“19”被排除在外。日期不是 1970 年,而是 70。计算机工程师缩短了日期,因为在那个时代,计算机中的数据存储成本高昂并且占用大量空间。<br> <br> 随着 2000 年的临近,计算机程序员意识到计算机可能不会将 00 解释为 2000,而是将其解释为 1900。每天或每年编程的所有活动都会受到损坏或有缺陷。当1999年12月31日变成2000年1月1日时,计算机会将1999年12月31日解释为变成1900年1月1日。<br> <br> 每天计算利率的银行和其他金融机构面临着实际问题。计算机将计算负 100 年的利率,而不是一天的利率。发电厂、交通运输和许多其他部门也将受到这一变化的影响。<br> <br> 美国政府通过了《2000年信息和准备披露法》为此次活动做准备,并成立了一个由政府高级官员和联邦应急管理局(FEMA)等机构官员组成的总统委员会,监督私营公司为活动准备系统的工作。研究公司Gartner估计,避免千年虫的全球成本可能高达6000亿美元。<br> <br> 吸取了上述七个教训,要记得务必在初始阶段测试软件,以避免损坏和修复的高成本。</p> 炒蚕豆吃蹦豆 2023-05-27 https://www.v2tn.com/content/168519775360563
被动防御→积极防御,系统稳定性保障思路启发 https://www.v2tn.com/content/1685193005497706 <p style="color:#000000; text-align:start">随着数据化和信息化浪潮的深入,系统的架构在不断地演变,实现了<strong>从“单线程”到“多线程、多组件”再到“分布式、微服务”的一个跨越。</strong>目前国内外中大型企业基本都采用的是分布式系统架构,复杂程度高。<br> ​机器是异构的,不同的机器厂商,会出现配置不同、运算、存储性能不同、网络延迟、带宽不同的情况。业务系统是分布式的,中间件也是分布式,网络也会有各种各样的节点,我们没办法去保证每一个节点它都是绝对可用的。这里面的任何一环出现问题,都可能引发系统故障。2020年,新冠疫情使得实体经济遭受重创,倒逼<strong>各行业加速进行数字化转型升级 。</strong>随着人们消费习惯的变更,数字经济开始崭露头角,不断扩张的庞大用户群体在一些特定的场景下同时涌入系统,对分布式系统稳定性发起更高的挑战,导致故障频发。</p> <p style="color:#000000; text-align:center"><img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/6d5255b31b2a48be8bc9694066e88715.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;国外亚马逊、谷歌云都曾挂机过,天猫双十一系统故障甚至上了微博热搜以及央视报道,就在2021 年,滴滴早高峰也出现系统问题,就连美联储也逃不开系统故障。这些事故都在说明一个事实——<strong>目前大多数的企业和组织并没有找到合适的系统故障应对方式,多数仍旧采取被动防御的方式,</strong>结果往往不尽如人意。那么究竟该如何保障庞大复杂的分布式系统的稳定性,走出故障频发的困局呢?</p> <p style="color:#000000; text-align:start">&nbsp;</p> <span></span> <h2><strong>毛教员教你要学会“积极防御”</strong></h2> <p style="color:#000000; text-align:start">毛教员对中国的影响源远流长,他“积极防御”的战略思想,是指导中国革命战争全局与国家军事斗争全局的根本战略思想,奠定了中国稳定长足发展的基石。这对于我们来说有很强的指导意义,不同的是我们的斗争对象是系统故障,目标是保障系统稳定。</p> <p style="color:#000000; text-align:start">&nbsp;《矛盾论》和《实践论》是毛泽东思想的精华凝聚,先来回顾一下:矛盾论主要讲的是矛盾具有普遍性与特殊性、主次矛盾以及矛盾的主次方面;实践论主要讲的是实践是认知的来源与发展动力,实践也是检验认知的标准。</p> <p style="color:#000000; text-align:start">分布式系统的稳定性保障本身就比较难,再加上高峰流量场景,比如常见的双 11 或者是突发疫情导致行程卡的访问比平常多 20 倍的情况,我们该怎么保证系统的稳定性?想要解决这个问题,首先要去识别它的主要矛盾和次要矛盾,进而再去改变不稳定的现状。那主要矛盾是什么?我们又该怎么做到“积极防御”呢?</p> <p style="color:#000000; text-align:start">笔者认为这个主要矛盾就是超大流量冲击超复杂的系统,依旧靠单点去做评估,要知道仅从单点去突破,没有从全局去考虑就没有把握能取得全局的稳定性。</p> <p style="color:#000000; text-align:start">“积极防御”当然这不是嘴上说说就行的,具体还是要进行实践。我们可以向安全行业取取经,“现在的安全是以合规作为检验标准,比如某个单位有没有安全设备,如果有了是不是代表有安全的能力?安全讲一百遍不如打一遍。”360集团董事长兼CEO周鸿祎在某次国际论坛上表示<strong>实战应该作为检验能力的唯一标准,</strong>而他所说的打一遍就是要对线上系统做攻防演练。同理系统稳定性保障也是如此,<strong>主动进行峰值流量系统全链路压测、容量演练是解决主要矛盾的关键一步。</strong></p> <span></span> <h2><strong>用实践教你如何正确构建积极防御体系</strong></h2> <p style="color:#000000; text-align:center"><strong><strong><img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/aed54ba7683648a0a002b2f140fc7425.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></strong></strong></p> <p style="color:#000000; text-align:start">&nbsp;先来看一组数据,2017年故障时长1106min到2020年的0min,这是怎么做到的?</p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start">今天就借用物流行业的一家企业实践经验来告诉大家如何构建积极防御体系。该企业从2017年开始发展快递业务,到2021年Q3, 收入从70亿快速增长三倍到现在的200亿,随着业务的不断扩张,企业的IT系统也在经历着天翻地覆的变化,为了保障业务的稳定发展,系统的稳定性保障也逐渐从被动防御转向积极防御。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/5e291d3905e24c1aa17fdf41019d8d75.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <span></span> <h3><strong>测试环境压测</strong></h3> <p style="color:#000000; text-align:start">2017年他们采用的方式是搭建性能测试环境进行系统压测,可耗费了大量的人力、硬件资源成本,最后得到的效果还是差强人意,当年双十一0点系统还是出现了故障,崩溃2小时导致无法接单,损失惨重。由于测试环境的差异性,一些故障只有在线上才会显现,当出现故障后再进行排查定位修复这就是被动防御,无法保障系统持续稳定可用。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/35a81a43b8dc4e0eab5d79658681b334.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <span></span> <h3><strong>生产全链路压测</strong></h3> <p style="color:#000000; text-align:start">意识到问题所在,他们想要参考阿里双十一,采用生产环境来做全链路压测,主动进行生产环境系统稳定性验证。这里就遇到了一个核心难点——实现数据隔离,阿里采用的是通过改造中间件实现压测数据的识别和转发到影子区域的方案,可这并不适用于所有的企业。许多企业与该物流公司一样存在中间件不统一、人才储备稀缺、成本考量的问题。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/e33afadec33647468e0319d257e2d9c0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start">最终他们采用了市面上成熟的开源产品Takin,利用JavaAgent字节码增强技术,无需改造业务系统,从JVM层面来实现压测数据的识别和转发。只要装了Takin的 Agent 探针,压测流量自己就会乖乖去到这个影子库里面。当然还有一个很重要的东西,如果我是一个支付请求,我不能把压测请求转发到支付宝或微信,Takin的挡板功能就能帮助拦截。此外也有一些 job 或者 check job,只要安装了探针,也可以虚拟出 job 的影子进程去做这个事情。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/52dae152195b491b8ce4808f3b4cc6ec.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start"><img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/3f6ffccfef29460c8426b3ed5c024071.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16">平台工具只是实现目标的一个手段,具体的实施过程其实非常重要,也会影响到最终的保障效果,生产环境全链路压测在实施中有6项关键性的工作。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/4fbcbca54bb447bea42a510a73a0e69b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start">压测是一个团队协同配合的工作,演练一方面是演练系统,另一方面是演练整个组织的这个应急反应的体系,所以基本上整个过程 IT 团队的每个角色基本上都要参与进来。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/38bb23e7170f48bbaf002cb72a98028e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start"><strong>通过生产环境全链路压测该企业在硬件资源投入方面减少了63%,在人力投入方面减少了65%,也达成了双十一高峰期间的系统0故障的目标。</strong></p> <span></span> <h3><strong>7*24H生产巡检</strong></h3> <p style="color:#000000; text-align:start">前面一直在讲通过演练去确保双 11 流量高峰系统没有问题,解决了主要矛盾,接下来要解决的次要矛盾了。业务量大、业务流程复杂,系统每天都要做发布,那怎么确保发布之后系统是没有问题的?或者说如果某个laaS层或者 pass 层的组件出了问题,怎么确保核心系统都是 OK 的?快递公司系统是 7 * 24 小时的运作的,并不是每一个核心服务都会持续有流量,以订单服务为例,白天流量会比较高,但到晚上就不高了,因为下订单的人都睡觉去了,而像中转服务它晚上才是流量高峰。曾有过这样的尴尬,晚上系统订单服务做了变更,到了第二天早上流量才 100 它就出现故障。很多时候可能都是这种非500或者非200的报错,甚至个直接抛一些 error 来,它并不是业务逻辑的错误。为了减少发布之后的系统意外,利用Takin中Agent的数据隔离能力,实现了真实流量在跑的时候同步进行巡检,此外利用测试流量进行7*24小时的业务巡检。通过设定响应时间、成功率去做系统监测,当实际响应时间/成功率超过预设值时,巡检系统就会发出提醒,服务飘红/飘黄。<img style='max-width:100%' alt="" src="https://img-blog.csdnimg.cn/2bc472098b6f4aa59e78ae82baf12ba6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16"></p> <p style="color:#000000; text-align:start">&nbsp;</p> <p style="color:#000000; text-align:start">总结一下,巡检就是把非业务逻辑的报错,通过技术相关的指标给直接反馈出来。后来该企业还基于巡检以及TakinAgent在生产环境实现了混沌工程,主动模拟注入故障来进一步检验系统的稳定性。</p> <p style="color:#000000; text-align:start">安全领域有个<strong>“零信任”理念:永不信任,持续验证。</strong>简单来说就是认为你每一次访问都是不安全的,然后不断地验证你的行为。<strong>映射到系统稳定性保障领域,当企业具备这种主动验证系统稳定性的能力,验证的次数越多,你收获的价值就越大。</strong>提前发现系统问题并解决,才能有效地保障业务的连贯性,同时能够将更多的时间投入到解决业务的问题上,积极防御的效益可见一斑。</p> <p style="color:#000000; text-align:start">文中提及的Takin产品核心代码已在Github上开源,有兴趣的可以自行了解。</p> <p style="color:#000000; text-align:start">开源地址:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FshulieTech%2FTakin" rel="nofollow" target="_blank">https://github.com/shulieTech/Takin</a></p> 数列科技 2023-05-27 https://www.v2tn.com/content/1685193005497706
7. 堪比JMeter的.Net压测工具 - Crank 总结篇 - crank带来了什么 https://www.v2tn.com/content/1685192978343675 <h2>1. 前言</h2> <p>通过上面的学习,我们已经了解清楚crank的职责以及作用,那么我们重新回来思考一下,crank能为我们带来什么?</p> <h2>2. Crank带来了什么?</h2> <ul> <li>为分布式压测提供了解决方案、可以模拟更高强度的压测 <ul> <li>单机压测最多提供65535,通过支持多个Agent可以很轻松的突破这个极限</li> </ul> </li> <li>提供了压测结果二次处理的能力,并支持将结果保存到json、csv、数据库甚至是es(<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank%2Fpull%2F375%2Ffiles" target="_blank">目前仍在对接</a>) <ul> <li>通过对以往压测数据的结果做折线图的展示</li> <li>通过ci可以完成自动化触发压测,再通过折线图清晰了解每次代码对性能的提升情况</li> </ul> </li> </ul> <h2>3. Crank还能更进一步吗?</h2> <p>上面的实战训练我们仅仅是做了基础的工作,尽管我们通过模拟多接口同时压测完成了对单场景的压测,但真实的项目远远不会是所有人都同时访问一个页面,而不访问其它页面,那我们如何模拟出更贴近真实场景的用户轨迹呢?</p> <p>真实的用户场景应该更像</p> <p><img style='max-width:100%' src="https://s2.loli.net/2022/02/22/lxgBwAiDUILNKeq.png" alt="用户行为"></p> <p>如果我们希望更进一步,想知道我们的系统的极限究竟在哪里,我们可以按照按照此用户场景进行深度还原压测场景,完成对整个场景的压测,并通过调整副本、带宽、Redis集群、数据库集群数量等方式提升QPS,最后通过不断的压测以及配置不断的增加,了解到我们使用什么样的配置、用多少副本、用多少带宽、什么样的Redis、数据库集群能够抗住多少的用户,但这个需要视我们真实的业务场景,如果QPS到100就够用的话,那么我们花费那么高的成本搞那么大的QPS有什么意义呢?我们又不是需要再做一个淘宝出来,实际没有那么高的用户量,搞到极致的优化也只是劳民伤财罢了</p> <h2>4. 疑问</h2> <ul> <li>Agent的压测机配置必须很高吗? <ul> <li>压测机的配置高,将赋予压测机更高的压测能力,但QPS的高低并不是通过压测机来决定,Qps低的项目,搞个超级计算机过来,Qps仍然低</li> </ul> </li> <li>为何我启动Agent执行任务后每次都需要Install Sdk?每次安装都需要半天,翻墙我也处理过了,但还是很慢 <ul> <li>建议Agent启动时指定dotnethome,并且在启动任务时,最好指定任务的框架环境是已经存在的环境,Agent的启动配置可以查看入门篇,指定任务运行框架可以查看进阶篇</li> </ul> </li> <li>为何我通过crank官方的命名运行出错呢? <ul> <li>crank还在持续更新升级中,可能会出现用新版本的crank发送上文示例不能使用的情况,可以安装指定版本的crank,以上示例都有在0.2.0-alpha.21567.1版本运行成功</li> </ul> </li> <li>我想自己搭建Agent的docker镜像,文中提供的镜像不知道是否安全? <ul> <li>文中用到的镜像是通过下面的dockerfile编译的,没有搞很复杂的东西,不放心的可以使用自建镜像</li> <li>doddgu/crankagent:net5.0是.net 5.0版本</li> </ul> </li> <li>我的压测场景也需要登录,但不需要实现每次请求都是一个新的用户,我该选择bombardier还是wrk、wrk2呢? <ul> <li>针对压测场景简单的,又不需要实现多用户、不需要动态参数的可以用bombardier、简单不需要学习lua、成本低</li> <li>希望可以用动态参数,玩一些复杂场景的,选择wrk或者wrk2更合适</li> </ul> </li> <li>压测场景单一,且不需要实现多用户、不需要动态参数不能使用wrk、wrk2吗? <ul> <li>bombardier能实现的场景,wrk、wrk2都可以做到</li> <li>针对简单的get请求,不需要更改参数使用wrk一样很简单、使用post请求的需要多掌握一点lua脚本知识,有条件的还是建议使用wrk、wrk2,它更灵活入手成本也不是太大</li> </ul> </li> </ul> <p><strong>crank agent dockerfile</strong></p> <pre><code>FROM mcr.microsoft.com/dotnet/sdk:5.0 ENV PATH="${PATH}:/root/.dotnet/tools" EXPOSE 5010 RUN dotnet tool install -g Microsoft.Crank.Agent --version "0.2.0-alpha.21567.1" ENTRYPOINT crank-agent --dotnethome "/usr/share/dotnet" </code></pre> <h2>5. 总结</h2> <p>Crank的功能其实是很单一的,它不像我们起初想象的那样庞大,所有的事情都能做,也没那么复杂,但我们也可以说Crank什么都能干,因为它提供了让我们运行dotnet项目以及在docker中运行dotnet程序的能力。</p> <p>但它最后能做什么事取决于使用它的人想用它来干什么,它只是一个工具而已,不要把它想得太美好,有了它以后可以不写代码,自动化完成测试工作,我只需要等结果,自动出报告等等……有这样想法的还是去洗洗脸吧,大白天的竟然在做梦?</p> <p>压测以及性能调优考验的是我们对整个系统的一个全局掌控能力,通过压测让我们知道目前系统的瓶颈在哪里?等我们的业务规模到了瓶颈时,可以通过调优提高项目的QPS、使其响应能力更快,不会因为系统而影响我们的业务,其目的是帮助业务发展的更好,但如果业务没发展起来,一味的陷入性能调优这个深坑中去,会使得我们花费高昂的代价做了没有实际意义的事,就比如说家里总共就四口人,非得搞个中巴,美其名曰可以拉更多的人,过年走亲戚不会坐不下什么的,每次出门费油又心疼的不得了,最后舍不得开了,最后还得花钱给它找停车位,那就得不偿失了</p> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192978343675
自动化测试的生命周期是什么? https://www.v2tn.com/content/1685192964566389 <p>软件测试发展到今日,已经逐渐标准化且能力更强,其流程每天都在发展。测试人员的技术熟练程度对于整个测试阶段的成功来说至关重要。测试不再意味着仅仅发现错误;它的范围已经扩大,从任何开发项目开始就可以看出它的重要性。<br> <br> 当谈论起自动化测试生命周期(Automation Testing Life Cycle)时,大多数人认为这只是 SDLC 的一部分,但它远不止于此。有必要了解自动化测试应该是自动化测试策略的突出部分,并且具有生命周期。企业必须对其进行调整以提高其软件产品的质量。<br> <br> 随着继续推进,需要能够回答以下问题:什么是自动化测试生命周期,以及自动化测试生命周期中的有哪些阶段。</p> <span></span> <h3>自动化测试生命周期的各个阶段</h3> <p>测试的自动化应该得到强大的测试计划的支持。流程的预定义结构有助于设计测试计划并制定自动化测试工具的选择策略,从而设置测试环境、设计测试用例并编写脚本。它进一步定义了测试自动化、测试准备、实施、测试验证和报告的范围。<br> <br> 自动化测试生命周期中的这六个阶段与软件开发周期并行运行。以下是各阶段:<br> <br> 阶段1:确定自动化测试的范围<br> 阶段2:选择合适的自动化工具<br> 阶段3:定义自动化测试的计划、策略和设计<br> 阶段4:设置测试环境<br> 阶段5:测试脚本和执行<br> 阶段6:测试分析和报告</p> <span></span> <h4>1. 确定自动化测试的范围</h4> <p>这是自动化测试生命周期的第一步。在此步骤中,测试团队需要确定自动化测试的可行性。可行性分析对于每个阶段都是必不可少的,以检查其可操作性,并帮助测试团队设计测试脚本。本阶段需要考虑的事项包括:<br> &nbsp;</p> <ul> <li>应用程序的哪些模块应该自动化,哪些模块不应该自动化。</li> <li>哪些测试用例可以或需要自动化。</li> <li>如何自动化这些测试用例。</li> <li>考虑到自动化与测试目标的适应性,选择哪些自动化工具。</li> <li>预算、实施成本、可用资源和可用技能。</li> </ul> <p><br> 测试用例和自动化测试可行性分析应在开始测试自动化之前进行。</p> <span></span> <h4>2. 选择合适的自动化工具</h4> <p><img style='max-width:100%' alt="" src="https://blog.easycorp.cn/file.php?f=zentao/202112/f_62d29852cc23f581f6ebee586c9a4c24&amp;t=jpg&amp;o=&amp;s=&amp;v=1638761400"></p> <p>这是ATLC最关键的阶段之一,因为自动化测试依赖于工具。要谨慎地考虑和选择正确的自动化工具来自动化UI组件。选择工具可能需要完成另一个层次的分析。在选择工具之前,应该始终牢记预算和成本。除此之外,团队还应分析资源是否具有技术技能,以及工具是否支持项目所需的技术。此外,该工具应提供强大的技术支持,以回答使用中可能存在的疑问。</p> <span></span> <h4>3.自动化测试的计划、策略和设计</h4> <p>这是自动化测试周期中的另一个关键步骤,主要解释实现测试自动化策略的方法。这个阶段的主要步骤是决定使用哪个测试自动化框架。在为项目选择合适的工具时,必须记住软件项目所需的技术。因此,对产品进行深入分析非常重要。<br> <br> 在执行自动化测试计划时,测试人员为测试过程创建、测试环境的硬件、软件和网络需求、测试数据先决条件、测试时间表、错误跟踪机制和工具等建立标准和指南。测试人员还负责决定测试体系结构、测试程序的结构和测试程序管理。<br> <br> 测试管理策略涵盖以下几点:</p> <ul> <li>测试管理工具将捕获所有手动测试用例。测试人员需要收集手动测试用例并确定哪些需要测试。</li> <li>必须进行彻底的研究来确定测试框架并了解自动化测试工具的优缺点。</li> <li>此外,测试人员还需要了解工具和应用程序之间的所有相关威胁、背景和依赖关系。</li> <li>团队还必须在测试管理工具中为自动化测试用例构建一个测试套件。</li> <li>未经利益相关者和客户批准,无法实施或执行制定的测试策略。</li> </ul> <span></span> <h4>4. 搭建测试环境</h4> <p>在此阶段,测试团队必须设置、跟踪和安排测试环境。换句话说,这意味着在这个阶段,建立了一个机器/远程环境来执行测试用例。需要虚拟机是因为并非所有用户都使用相同的机器来访问 Web 应用程序。因此,我们需要观察用户使用的各种设备、浏览器和版本。如果未正确验证其在不同设备-浏览器-操作系统组合之间的兼容性,网站效果跟用户看到的可能不一样。为了实现这一点,跨浏览器测试成为首要任务,以确保您的 Web 应用程序按预期提供出色的用户体验。&nbsp;<br> 此阶段需要详细规划以处理尽可能多的场景并增加测试覆盖率。在测试团队负责任的参与下,必须维护所有环境设置活动的正确跟踪和时间表。除此之外,设置测试环境、安排网络和硬件资源、执行测试数据库清理、开发测试平台和环境脚本等一切都必须处理。</p> <p>执行跨浏览器测试并不像听起来那么容易。它涉及设置不同的浏览器、不同的版本、不同的设备等,这对团队来说是个不小的负担。</p> <p>维护浏览器实验室并不是一件容易的事,因为从头开始建立和维护基础设施成本高昂,而且并非所有企业都能负担得起。因此,建议采用基于云的测试基础设施,为测试人员提供一个平台,以测试虚拟机托管的多个移动和桌面设备的各种浏览器设备操作系统组合。</p> <p><img style='max-width:100%' alt="" src="https://blog.easycorp.cn/file.php?f=zentao/202112/f_d4698abbe55fc7efa49a3bc8e3163869&amp;t=jpg&amp;o=&amp;s=&amp;v=1638779526"><br> 以下是测试环境设置的几个方面:</p> <ul> <li>确保有一个可以进行负载测试的前端运行环境,以检查其是否有能力处理高负载的Web流量。</li> <li>有时,设置的测试环境没有提供与生产数据相似的数据,使产品容易受到生产环境中任何代码更改的影响。</li> <li>需要进行测试的所有系统、模块和应用程序的列表应该进行维护检查。</li> <li>测试尽可能多的浏览器及其版本。</li> <li>跨多个客户端操作系统进行测试。</li> <li>需要用于登台环境的单独数据库服务器。</li> <li>确保在不同网络条件下测试 Web 应用程序,以了解实际的网站渲染时间和整体外观。</li> <li>在中央数据库中维护用户手册、安装指南和其他文档也是为未来需求设置测试环境的关键。</li> </ul> <span></span> <h4>5. 测试脚本和执行</h4> <p>配置测试环境设置后,下一步就是执行测试脚本。测试人员在开发测试脚本之前应该考虑以下几点:</p> <ul> <li>根据项目要求创建脚本。</li> <li>在整个过程中使用通用的方法。</li> <li>确保脚本可重用、简单且结构化,以便任何人都能理解它们。</li> <li>执行适当的代码审查和报告以获得更好的见解并在整个过程中保持质量。</li> </ul> <p>脚本开发完成后,需要牢记以下几点以确保脚本无障碍运行:</p> <ul> <li>根据测试用例,它们应该包括所有功能方面。</li> <li>它们应该涵盖执行测试脚本的所有平台和环境。。</li> <li>它们必须批量处理以节省时间和精力。</li> <li>要始终练习编写错误报告,以防出现任何功能错误。</li> </ul> <p>评估和记录测试结果以供进一步参考,并在 ATLC 的这一部分创建测试结果文档。</p> <span></span> <h4>6. 测试分析和报告</h4> <p>它是自动化测试生命周期的最后也是最关键的阶段,只保存数据而不进行分析并没有帮助。捕获所有测试结果后,要执行所有类型的测试,测试团队分析并识别有问题的功能。这些报告有助于了解团队是否需要附加程序,并提供有关遇到的不同错误的信息。准备一份详尽的报告,并与在此阶段对项目至关重要的利益相关者、客户、员工和团队共享。这些报告对于了解 Web 应用程序在不利情况下的行为至关重要。</p> <span></span> <h3>结论</h3> <p>毫无疑问,软件自动化测试是SDLC 不可或缺的一部分,是实现测试目标的最有效方法之一。但软件测试也有其自己的一组阶段,必须认真遵循这些阶段才能获得这种技术的好处。它允许使用任何可用资源在规定的时间内实现测试目标。遵循自动化测试生命周期的每一步都有助于获得最佳结果,无需任何人工干预并减少预算和时间表。精心规划的自动化测试生命周期会带来成功的自动化测试。</p> 炒蚕豆吃蹦豆 2023-05-27 https://www.v2tn.com/content/1685192964566389
6. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 收集诊断跟踪信息与如何分析瓶颈 https://www.v2tn.com/content/1685192928455136 <h2>1. 前言</h2> <p>上面我们已经做到了接口以及场景压测,通过控制台输出结果,我们只需要将结果收集整理下来,最后汇总到excel上,此次压测报告就可以完成了,但收集报告也挺麻烦的,交给谁呢……</p> <p>找了一圈、没找到愿意接手的人,该怎么办呢……思考了会儿还是决定看看能否通过程序解决我们的难题吧,毕竟整理表格太累╯﹏╰</p> <h2>2. 收集结果</h2> <p>通过查阅官方文档,我们发现官方提供了把数据保存成Json、csv、以及数据库三种方式,甚至还有小伙伴积极的对接要把数据保存到Es中,那选个最简单的吧!</p> <p>要不选择Json吧,不需要依赖外部存储,很简单,我觉得应该可试,试一下看看:输入命令:</p> <pre><code>crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --json 1.json --profile local --profile crankAgent1 --description "wrk2-获取用户详情" --profile defaultParamLocal </code></pre> <p>最后得到结果:</p> <pre><code>{ "returnCode": 0, "jobResults": { "jobs": { "load": { "results": { "http/firstrequest": 85.0, "wrk2/latency/mean": 1.81, "wrk2/latency/max": 1.81, "wrk2/requests": 2.0, "wrk2/errors/badresponses": 0.0, "wrk2/errors/socketerrors": 0.0, "wrk2/latency/50": 1.81, "wrk2/latency/distribution": [ [ { "latency_us": 1.812, "count": 1.0, "percentile": 0.0 }, { "latency_us": 1.812, "count": 1.0, "percentile": 1.0 } ] ] } } } } } </code></pre> <blockquote> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fraw.githubusercontent.com%2Fdoddgu%2Fcrank%2Fsample%2Fsamples%2Fwrk2%2Fbenchmarks%2Fapi%2Fget%2Fresult.json" target="_blank">完整的导出结果</a></p> </blockquote> <p>好吧,数据有点少,好像数据不太够吧,这些信息怎么处理能做成报表呢,再说了数据不对吧,QPS、延迟呢?好吧,被看出来了,因为信息太多,我删了一点点(也就1000多行指标信息吧),看来这个不行,用json的话还得配合个程序好难……</p> <p>csv不用再试了,如果也是单个文本的话,也是这样,还得配个程序,都不能单干,干啥都得搭伴,那试试数据库如何</p> <pre><code>crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --sql "Server=localhost;DataBase=crank;uid=sa;pwd=P@ssw0rd;" --table "local" --profile local --profile crankAgent1 --description "wrk2-获取用户详情" --profile defaultParamLocal </code></pre> <blockquote> <p>我们根据压测环境,把不同的压测指标存储到不同的数据库的表中,当前是本地环境,即 table = local</p> </blockquote> <p>最后我们把数据保存到了数据库中,那这样做回头需要报告的时候,我查询下数据库搞出来就好了,终于松了一口气,但好景不长,发现数据库存储也有个坑,之前json中看到的结果竟然在一个字段中存储,不过幸好SqlServer 2016之后支持了json,可以通过json解析搞定,但其中参数名有/等特殊字符,sql server处理不了,难道又得写个网站才能展示这些数据了吗??真的绕不开搭伴干活这个坑吗?</p> <p>微软不会就做出个这么鸡肋的东西,还必须要配个前端才能清楚的搞出来指标吧……还得用vue、好吧,我知道虽然现在有<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fdoddgu%2Fp%2Fmasa-blazor-0.html" target="_blank">blazer</a>,可以用C#开发,但还是希望不那么麻烦,又仔细查找了一番,发现Crank可以对结果做二次处理,可以通过script,不错的东西,既然sql server数据库无法支持特殊字符,那我加些新参数取消特殊字符不就好了,新建scripts.profiles.yml</p> <pre><code>scripts: changeTarget: | benchmarks.jobs.load.results["cpu"] = benchmarks.jobs.load.results["benchmarks/cpu"] benchmarks.jobs.load.results["cpuRaw"] = benchmarks.jobs.load.results["benchmarks/cpu/raw"] benchmarks.jobs.load.results["workingSet"] = benchmarks.jobs.load.results["benchmarks/working-set"] benchmarks.jobs.load.results["privateMemory"] = benchmarks.jobs.load.results["benchmarks/private-memory"] benchmarks.jobs.load.results["totalRequests"] = benchmarks.jobs.load.results["bombardier/requests;http/requests"] benchmarks.jobs.load.results["badResponses"] = benchmarks.jobs.load.results["bombardier/badresponses;http/requests/badresponses"] benchmarks.jobs.load.results["requestSec"] = benchmarks.jobs.load.results["bombardier/rps/mean;http/rps/mean"] benchmarks.jobs.load.results["requestSecMax"] = benchmarks.jobs.load.results["bombardier/rps/max;http/rps/max"] benchmarks.jobs.load.results["latencyMean"] = benchmarks.jobs.load.results["bombardier/latency/mean;http/latency/mean"] benchmarks.jobs.load.results["latencyMax"] = benchmarks.jobs.load.results["bombardier/latency/max;http/latency/max"] benchmarks.jobs.load.results["bombardierRaw"] = benchmarks.jobs.load.results["bombardier/raw"] </code></pre> <blockquote> <p>以上处理的数据是基于bombardier的,同理大家可以完成对wrk或者其他的数据处理</p> </blockquote> <p>通过以上操作,我们成功的把特殊字符的参数改成了没有特殊字符的参数,那接下来执行查询sql就可以了。</p> <pre><code>SELECT Description as '场景', JSON_VALUE (Document,'$.jobs.load.results.cpu') AS 'CPU使用率(%)', JSON_VALUE (Document,'$.jobs.load.results.cpuRaw') AS '多核CPU使用率(%)', JSON_VALUE (Document,'$.jobs.load.results.workingSet') AS '内存使用(MB)', JSON_VALUE (Document,'$.jobs.load.results.privateMemory') AS '进程使用的私有内存量(MB)', ROUND(JSON_VALUE (Document,'$.jobs.load.results.totalRequests'),0) AS '总发送请求数', ROUND(JSON_VALUE (Document,'$.jobs.load.results.badResponses'),0) AS '异常请求数', ROUND(JSON_VALUE (Document,'$.jobs.load.results.requestSec'),0) AS '每秒支持请求数', ROUND(JSON_VALUE (Document,'$.jobs.load.results.requestSecMax'),0) AS '每秒最大支持请求数', ROUND(JSON_VALUE (Document,'$.jobs.load.results.latencyMean'),0) AS '平均延迟时间(us)', ROUND(JSON_VALUE (Document,'$.jobs.load.results.latencyMax'),0) AS '最大延迟时间(us)', CONVERT(varchar(100),DATEADD(HOUR, 8, DateTimeUtc),20) as '时间' FROM dev; </code></pre> <h2>3. 如何分析瓶颈</h2> <p>通过上面的操作,我们已经可以轻松的完成对场景的压测,并能快速生成相对应的报表信息,那正题来了,可以模拟高并发场景,那如何分析瓶颈呢?毕竟报告只是为了知晓当前的系统指标,而我们更希望的是知道当前系统的瓶颈是多少,怎么打破瓶颈,完成突破呢……</p> <p>首先我们要先了解我们当前的应用的架构,比如我们现在使用的是微服务架构,那么</p> <ul> <li>应用拆分为几个服务?了解清楚每个服务的作用</li> <li>服务之间的调用关系</li> <li>各服务依赖的基础服务有哪些、基础服务基本的信息情况</li> </ul> <p>举例我们当前的微服务架构如下:</p> <p><img style='max-width:100%' src="https://s2.loli.net/2022/02/22/yC3MWwnfqI8NaLT.png" alt="架构"></p> <p>通过架构图可以快速了解到项目结构,我们可以看到用户访问web端,web端根据请求对应去查询redis或者通过http、grpc调用服务获取数据、各服务又通过redis、db获取数据。</p> <p>首先我们先通过crank把当前的数据指标保存入库。调出其中不太理想的接口开始分析。</p> <p>在这里我们拿两个压测接口举例:</p> <ul> <li>获取首页Banner、QPS:3800 /s (Get)</li> <li>下单、QPS:8 /s (Post)</li> </ul> <h3>3.1. 获取首页Banner</h3> <p>通过单测首页banner的接口,QPS是3800多不到4000这样,虽然这个指标还不错,但我们仍然觉得很慢,毕竟首页banner就是很简单几个图片+标题组合的数据,数据量不大,并且是直连Redis,仅在Redis不存在时才查询对应服务获取banner数据,这样的QPS实在不应该,并且这个还是仅压测单独的banner,如果首页同时压测十几个接口,那其性能会暴降十倍不止,这样肯定是不行的</p> <p>我们又压测了一次首页banner接口,发现有几个疑点:</p> <ul> <li>redis请求数徘徊在3800左右的样子,网络带宽占用1M的样子,无法继续上涨</li> <li>查看web服务,发现时不时的会有调用服务超时出错的问题,Db的访问量有上涨,但不明显,很快就下去了</li> </ul> <blockquote> <p>思考: Redis的请求数与最后的压测结果差不多,最后倒也对上了,但为什么redis的请求数这么低呢?难道是带宽限制!!</p> </blockquote> <p><img style='max-width:100%' src="https://s2.loli.net/2022/02/22/hHKk8Cr6zagc3Ao.png" alt="结构"></p> <p>虽然是单机redis,但4000也绝对不可能是它的瓶颈,怀疑是带宽被限制了,应该就是带宽被限制了,后来跟运维一番切磋后,得到结论是redis没限制带宽……</p> <p>那为什么不行呢,这么奇怪,redis不可能就这么点并发就不行了,算了还是写个程序试一下吧,看看是不是真的测试环境不给力,redis配置太差了,一番操作后发现,同一个redis数据,redis读可以到6万8,不到7万、带宽占用10M,redis终于洗清了它的嫌疑,此接口的QPS不行与Redis无关,但这么简单的一个结构为什么QPS就上不去呢……,如果不是redis的问题,那会不会是因为请求就没到redis上,是因为压测机的强度不够,导致请求没到redis……当时冒出来这个有点愚蠢的想法,那就增加压测机的数量,通过更改负载压测机配置,1台压测机升到了3台,但可惜的是单台压测机的指标不升反降,最后所有压测机的指标加到一起正好与之前一台压测机的压测结果差不多一样,那说明QPS低与压测机无关,后来想到试试通过增加多副本来提升QPS,后来web副本由1台提升到了3台,之前提到的服务调用报错的情况更加严重,之前只是偶尔有一个错误,但提升web副本后,看到一大片的错误</p> <ul> <li>提示Thread is busy,很多线程开始等待</li> <li>大量的服务调用超时,DB查询缓慢</li> </ul> <p>最后QPS 1000多一点,有几千个失败的错误,这盲目的提升副本貌似不大有效,之前尽管Qps不高,但起码也在4000,DB也没事,这波神操作后QPS直降4分之3,DB还差点崩了,思想滑坡了,做了负优化……</p> <p>继续思考,为何提升副本,QPS不升反降,为何出现大量的调用超时、为何DB会差点被干崩,我只是查询个redis,跟DB有毛关系啊!奇了怪了,看看代码怎么写的吧……烧脑</p> <pre><code>public async Task&lt;List&lt;BannerResponse&gt;&gt; GetListAsync() { List&lt;BannerResponse&gt; result = new List&lt;BannerResponse&gt;(); try { var cacheKey = "banner_all"; var cacheResult = await _redisClient.GetAsync&lt;List&lt;BannerResponse&gt;&gt;(cacheKey); if (cacheResult == null) { result = this.GetListServiceAsync().Result; _redisClient.SetAsync(cacheKey, result, new() { DistributedCacheEntryOptions = new() { AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(5) } }).Wait(); } else { result = cacheResult; } } catch (Exception e) { result = await this.GetListServiceAsync(); } return result; } </code></pre> <p>看了代码后发现,仅当Reids查询不到的时候,会调用对应服务查询数据,对应服务再查询DB获取数据,另外查询异常时,会再次调用服务查询结果,确保返回结果一定是正确的,看似没问题,但为何压测会出现上面那些奇怪现象呢……</p> <p>请求超时、大量等待,那就是正好redis不存在,穿透到对应的服务查询DB了,然后压测同一时刻数据量过大,同一时刻查询到的Reids都是没有数据,最后导致调用服务的数量急剧上升,导致响应缓慢,超时加剧,线程因超时释放不及时,又导致可用线程较少。</p> <p>这块我们查找到对应的日志显示以下信息</p> <pre><code>System.TimeoutException: Timeout performing GET MyKey, inst: 2, mgr: Inactive, queue: 6, qu: 0, qs: 6, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, IOCP: (Busy=6,Free=994,Min=8,Max=1000), WORKER: (Busy=152,Free=816,Min=8,Max=32767) </code></pre> <ul> <li>那么我们可以调整Startup.cs:</li> </ul> <pre><code>public void ConfigureServices(IServiceCollection services) { ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads); ThreadPool.SetMinThreads(1000, completionPortThreads);//根据情况调整最小工作线程,避免因创建线程导致的耗时操作 ……………………………………………………………此处省略………………………………………………………………………………………………………… } </code></pre> <ul> <li>web服务调用底层服务太慢,那么提升底层服务的响应速度(优化代码)或者提高处理能力(提升副本)</li> <li>防止高并发情况下全部穿透到下层,增加底层服务的压力</li> </ul> <p>前两点也是一个好的办法,但不是最好的解决办法,最好还是不要穿透到底层服务,如果reids不存在,就放一个请求过去是最好的,拿到数据就持久化到redis,不要总穿透到下层服务,那么怎么做呢,最简单的办法就是使用加锁,但加锁会影响性能,但这个我们能接受,后来调整加锁测试,穿透到底层服务的情况没有了,但很可惜,请求数确实会随着副本的增加而增加,但是实在是有点不好看,后来又测试了下另外一个获取缓存数据的结果,结果QPS:1000多一点,比banner还要低的多,两边明明都使用的是Reids,性能为何还有这么大的差别,为何我们写的redis的demo就能到6万多的QPS,两边都是拿的一个缓存,差距有这么大?难道是封装redis的sdk有问题?后来仔细对比了后来写的redis的demo与banner调用redis的接口发现,一个是直接查询的redis的字符串,一个是封装redis的sdk,多了一个反序列化的过程,最后经过测试,反序列化之后性能降低了十几倍,好吧看来只能提升副本了……但为何另外的接口也是从redis获取,性能跟banner的接口不一样呢!!</p> <p>经过仔细对比发现,差别是信息量,QPS更低的接口的数据量更大,那结果就有了,随着数据量的增加,QPS会进一步降低,那这样一来的话,增加副本的作用不大啊,谁知道会不会有一个接口的数据量很大,那性能岂不是差的要死,那还怎么玩,能不能提升反序列化的性能或者不反序列化呢,经过认真思考,想到了二级缓存,如果用到了二级缓存,内存中有就不需要查询redis,也不需要再反序列化,那么性能应该有所提升,最后的结构如下图:</p> <p><img style='max-width:100%' src="https://s2.loli.net/2022/02/22/iDCWFYvG7gnLHoP.png" alt="结构"></p> <p>最后经过压测发现,单副本QPS接近50000,比最开始提升12倍,并且也不会出现服务调用超时,DB崩溃等问题、且内存使用平稳</p> <p>此次压测发现其banner这类场景的性能瓶颈在反序列化,而非Redis、DB,如果按照一开始不清楚其工作原理、盲目的调整副本数,可能最后会加剧系统的雪崩,而如果我们把DB资源、Redis资源盲目上调、并不会对最后的结果有太大帮助,最多也只是延缓崩溃的时间而已</p> <h3>3.2. 下单</h3> <p>下单的QPS是8,这样的QPS已经无法忍受了,每秒只有十个请求可以下单成功,如果中间再出现一个库存不足、账户余额不足、活动资格不够等等,实际能下单的人用一个手可以数过来,真的就这么惨……虽然下单确实很费性能,不过确实不至于这么低吧,先看下下单流程吧</p> <p><img style='max-width:100%' src="https://s2.loli.net/2022/02/22/2Gxg5fCy19RlNeu.png" alt="下单"></p> <p>简化后的下单流程就这么简单,web通过dapr的actor服务调用order service,然后就是漫长的查询db、操作redis操作,因涉及业务代码、具体代码就不再放出,但可以简单说一下其中做的事情,检查账户余额、反复的增加redis库存确保库存安全、检查是否满足活动、为推荐人计算待结算佣金等等一系列操作,整个看下来把人看懵了,常常是刚看了上面的,看下面代码的时候忘记上面具体干了什么事,代码太多了,一个方法数千行,其中再调用一些数百行的代码,真的吐血了,不免感叹我司的开发小哥哥是真的强大,这么复杂的业务居然能这么"顺畅"的跑起来,后面还有N个需求等待加到下单上,果然不是一般人</p> <p>不过话说回来,虽然是业务是真的多,也真的乱,不过这样搞也不至于QPS才只有8这么可怜吧,服务器的处理能力可不是二十几年前的电脑可以比拟的,单副本8核16G的配置不支持这么拉胯吧,再看一下究竟谁才是真正的幕后黑手……</p> <p>但究竟哪里性能瓶颈在哪里,这块就要出杀手锏了</p> <p><img style='max-width:100%' src="https://s2.loli.net/2022/02/22/n3xdzatfZvVlkXG.png" alt="Tracing"></p> <p>通过Tracing可以很清楚的看到各节点的耗时情况,这将对我们分析瓶颈提供了非常大的帮助、我们看到了虽然有几十次的查询DB操作,但DB还挺给力,基本也再很短时间内就给出了响应,那剩余时间耗费到了哪里呢?我们看到整体耗时11s、但查询Db加起来也仅仅不到1s,那么剩余操作都在哪里?要知道哪怕我们优化DB查询性能,减少DB查询,那提升的性能对现在的结果也是微乎其微</p> <p>结合Tracing以及下单流程图,我们发现从Web到Order Service是通过<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fdoddgu%2Fp%2Fdapr-learning-7.html" target="_blank">actor</a>来实现的,那会不是这里耗时影响的呢?</p> <p>但dapr是个新知识、开发的小哥哥速度真快,这么快就用上dapr了(ˇˍˇ)不知道小哥哥的头发还有多少……</p> <p>快速去找到下单使用actor的地方,如下:</p> <pre><code>[HttpPost] [Authorize] public async Task&lt;CreateOrderResponse&gt; CreeateOrder([FromBody] CreateOrderModel request) { string actionType = "SalesOrderActor"; var salesOrderActor = ActorProxy.Create&lt;ISalesOrderActor&gt;(new ActorId(request.SkuList.OrderBy(sku =&gt; sku.Sku).FirstOrDefault().Sku), actionType); request.AccountId = Account.Id; var result = await salesOrderActor.CreateOrderAsync(request); return new Mapping&lt;ParentSalesOrderListViewModel, CreateOrderResponse&gt;().Map(result); } </code></pre> <p>我们看到了这边代码十分简单,获取商品信息的第一个sku编号作为actor的actorid使用,然后得到下单的actor,之后调用actor中的创建订单方法最后得到下单结果,这边的代码太简单了,让人心情愉快,那这块会不会有可能影响下单速度呢?它是不是那个性能瓶颈最大的幕后黑手?</p> <p>首先这块我们就需要了解下什么是Dapr、Actor又是什么,不了解这些知识我们只能靠抓阄来猜这块是不是瓶颈了……</p> <blockquote> <p>Dapr 全称是Distributed Application Runtime,分布式应用运行时,并于今年加入了 CNCF 的孵化项目,目前Github的star高达16k,相关的学习文档在文档底部可以找到,我也是看着下面的文档了解dapr</p> </blockquote> <p>通过了解actor,我们发现用sku作为actorid是极不明智的选择,像秒杀这类商品不就是抢的指定规格的商品吗?如果这样一来,这不是在压测actor吗?这块我们跟对应的开发小哥哥沟通了下,通过调整actorid顺利将Qps提升到了60作用,后面又通过优化减少db查询、调整业务规则的顺序等操作顺利将QPS提升到了不到一倍,虽然还是很低,不过接下来的优化工作就需要再深层次的调整业务代码了……</p> <h2>4. 总结</h2> <p>通过实战我们总结出分析瓶颈从以下几步走:</p> <ol> <li>通过第一轮的压测获取性能差的接口以及指标</li> <li>通过与开发沟通或者自己查看源码的方式梳理接口流程</li> <li>通过分析其项目所占用资源情况、依赖第三方基础占用资源情况以及Tracing更进一步的确定瓶颈大概的点在哪几块</li> <li>通过反复测试调整确定性能瓶颈的最大黑手</li> <li>将最后的结论与相关开发、运维人员沟通,确保都知晓瓶颈在哪里,最后优化瓶颈</li> </ol> <p>知识点:</p> <ul> <li>Dapr <ul> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fdoddgu%2Fp%2Fdapr-learning-1.html" target="_blank">手把手教你学Dapr系列</a></li> </ul> </li> <li>Tracing <ul> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fdalianpai%2Fp%2F14032431.html" target="_blank">OpenTracing 简介</a>、关于OpenTracing后续我们也会开源,可以提前关注我们的开源项目 <ul> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">Masa.BuildingBlocks</a></li> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">Masa.Contrib</a></li> </ul> </li> </ul> </li> </ul> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192928455136
5. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 接口以及场景压测 https://www.v2tn.com/content/1685192888697174 <h2>1. 前言</h2> <p>通过之前的学习,我们已经掌握了crank的配置以及对应http基准工具bombardier、wrk、wrk2的用法,本篇文章介绍一下如何将其用于实战,在实际的项目中我们如何使用crank来完成压测任务。</p> <h2>2. 项目背景</h2> <p>目前有一个项目,我们希望通过压测来了解其QPS、吞吐量、以及临界值,并通过压测来分析出其瓶颈在哪里?并通过解决瓶颈问题以提高QPS、吞吐量等指标</p> <p>先看下我们手头掌握了什么:</p> <ul> <li>项目信息 <ul> <li>项目中的接口基本都需要登录</li> <li>通过与开发沟通可以得到每个页面的接口信息以及参数信息</li> </ul> </li> <li>环境信息 <ul> <li>压测项目有单独的环境部署应用、Redis、数据库等基础配置</li> </ul> </li> </ul> <p>此处项目名我们暂定为ProjectA。</p> <h2>3. 如何开展</h2> <p>首先我们先回顾一下Agent、Controller的职责以及特点</p> <ul> <li>Controller <ul> <li>做任务调度以及结果输出</li> <li>无需单独服务器,可以在本机执行发送命令,需要与Agent相通</li> </ul> </li> <li>Agent <ul> <li>任务的实际执行者</li> <li>单任务执行,不能做到接收到多个任务并同时执行,先收到哪个任务,哪个任务会先执行</li> <li>相同一个任务可以被多个Agent同时执行,最终指标结果会自动累加,可以通过提升Agent来模拟更高的并发能力</li> </ul> </li> </ul> <h3>3.1. 思路</h3> <ul> <li>先做好单独接口的压测,大概掌握每个接口的指标情况</li> <li>同时压测多个接口,完成对场景的压测</li> <li>通过压测观察应用服务器、基础服务器的CPU、带宽、内存等指标,观察Redis、数据库、消息队列等基础组件情况,根据压测的返回结果得到每个场景的基础指标</li> <li>通过分析发现瓶颈、然后再考虑如何突破瓶颈,提升QPS、吞吐量等</li> </ul> <h3>3.2. 如何做?</h3> <p>了解到单个Agent同时执行多个任务会进行排队,无法做到多任务同时执行,那么我们可以通过多个Agent同时执行不同的任务来模拟用户访问页面。</p> <h4>3.2.1. 构建Agent</h4> <p>之前与开发沟通得到每个页面最多可发送的请求是6个,那么我们准备6个Agent,分别为Agent1、Agent2、Agent3、Agent4、Agent5、Agent6</p> <p>我们这里使用Docker来启动Agent、Agent对内开放端口: 5010、对外端口随机,镜像使用我们自建的: doddgu/crankagent:net5.0</p> <p>并新建load.yml为之后压测使用:</p> <pre><code>profiles: crankAgent1: jobs: load: endpoints: - http://localhost:5010 crankAgent2: jobs: load: endpoints: - http://localhost:5011 crankAgent3: jobs: load: endpoints: - http://localhost:5012 crankAgent4: jobs: load: endpoints: - http://localhost:5013 crankAgent5: jobs: load: endpoints: - http://localhost:5014 crankAgent6: jobs: load: endpoints: - http://localhost:5015 </code></pre> <blockquote> <p>load.yml 中记录了所有的压测机信息,其信息一般不做修改,我们可以作为公共的配置来使用无需每个项目都单独维护一份新的</p> </blockquote> <h4>3.2.2. 构建压测脚本</h4> <p>在这里我们选择wrk2作为本次基准测试工具,选择wrk2的原因是:</p> <ul> <li>支持随机参数</li> <li>可支持设置恒定的吞吐量负载</li> <li>具备wrk的所有功能</li> </ul> <p>此时我们针对ProjectA项目新建配置:project.profiles.yml,作为本次压测的环境配置来使用,其配置如下</p> <pre><code>imports: - https://raw.githubusercontent.com/doddgu/crank/sample/samples/wrk2/common/load.profiles.yml # 这边建议使用远程load.profiles.yml地址。(如果输入的是本地路径、则需输入与当前命令所在路径的相对路径) profiles: local: # 本地环境 variables: serverAddress: localhost # 应用服务域 serverPort: 80 # 应用服务端口 connections: 256 # 每个线程处理时保持打开的 HTTP 连接总数 N = 连接数/线程数 threads: 32 # 线程数 warmup: 3 # 预热时间: 3s duration: 180 # 测试时长: 3分钟 rate: # 吞吐量参数(每秒总请求数) </code></pre> <blockquote> <p>project.profiles.yml中记录了指定项目的各环境的配置,项目自己独立维护即可</p> </blockquote> <p>除了项目信息、压测机配置之外,我们还需要有地方维护我们压测的接口信息,这边我的做法是将api独立拆分出来,每个yml只配置一个接口的压测信息,至于为什么不放到一块,而要单独拆分开呢?</p> <p>这块考虑到我们压测的最小单元是API接口,如果把API接口独立拆分开,那么可以对单接口压测,而如果我们需要场景压测,也可以通过组合接口完成多接口同时压测,并且一旦我们完成了某个接口的压测编写,后续不需要再改动这个配置,如果我们按照场景拆分成不同的yml,在yml中再根据定义不同的scenario来做,那么后续场景新增加接口,还需要再更改这个场景的yml,并且scenario中的场景实际上也是根据接口维度区分的,目前crank并不能完成单个场景任务同时处理,基于以上原因,这边我们新调整好的配置格式为:</p> <p>新增load.benchmarks.yml</p> <pre><code>imports: - https://raw.githubusercontent.com/doddgu/crank/sample/src/Microsoft.Crank.Jobs.Wrk2/wrk2.yml - https://raw.githubusercontent.com/doddgu/crank/sample/samples/wrk2/common/project.profiles.yml jobs: server: source: repository: https://github.com/doddgu/crank branchOrCommit: sample project: samples/hello/hello.csproj readyStateText: Application started. scenarios: api: application: # 实际压测项目时可移除此节点,此处是为模拟应用服务启动 job: server variables: duration: 1 load: job: wrk2 variables: serverPath: /user/get script: request.lua duration: 1 profiles: defaultParamLocal: # 本地环境的参数信息 variables: serverQueryString: ?id={1} serverQueryParameter: 1||2 # 随机请求/get?id=1、/get?id=2 </code></pre> <p>按照此格式保存,后续新增接口也可以快速复制,简单修改即可快速完成压测工作的编写,这样一来,如果我们希望对localhost:5000/user/get这个接口做压测,仅需要在crank控制端输入:</p> <pre><code>crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --profile local --profile crankAgent1 --description "获取用户详情" --profile defaultParamLocal </code></pre> <h4>3.2.3. 构建批处理命令</h4> <p>但作为一个开发人员,总是希望事情能更简单一点,每次输入命令太麻烦了,所以就想到了通过批处理快速完成任务的发送,最终的项目结构就变成了</p> <pre><code>benchmarks ├─ defaultTitle 接口名称( Description ) └─ load.bat 最终执行的脚本,其中指定了要指定的yml配置、场景、以及任务环境是.net 5.0 └─ load.benchmarks.yml yml配置 └─ load.local.bat 测试本地环境时要执行的脚本、格式:load.{环境}.bat └─ README.md 帮助文档 </code></pre> <p>每次通过双击load.{环境}.bat就完成了对当前接口的压力测试,然后就是等待结果输出……</p> <pre><code>| application | | | --------------------- | -------------- | | CPU Usage (%) | 1 | | Cores usage (%) | 10 | | Working Set (MB) | 85 | | Private Memory (MB) | 278 | | Build Time (ms) | 3,469 | | Start Time (ms) | 352 | | Published Size (KB) | 93,323 | | .NET Core SDK Version | 5.0.404 | | ASP.NET Core Version | 5.0.13+55738ff | | .NET Runtime Version | 5.0.13+b3afe99 | | load | | | --------------------- | -------------- | | Build Time (ms) | 3,281 | | Start Time (ms) | 0 | | Published Size (KB) | 74,276 | | .NET Core SDK Version | 5.0.404 | | ASP.NET Core Version | 5.0.13+55738ff | | .NET Runtime Version | 5.0.13+b3afe99 | | First Request (ms) | 86 | | Requests/sec | 2 | | Requests | 2 | | Mean latency (ms) | 2.68 | | Max latency (ms) | 2.68 | | Bad responses | 0 | | Socket errors | 0 | | Latency 50th (ms) | 2.68 | | Latency 75th (ms) | 2.68 | | Latency 90th (ms) | 2.68 | | Latency 99th (ms) | 2.68 | | Latency 99.9th (ms) | 2.68 | | Latency 99.99th (ms) | 2.68 | | Latency 99.999th (ms) | 2.68 | </code></pre> <h4>3.2.4. 构建场景压测批处理命令</h4> <p>通过上面的一番操作,我们已经可以很容易的对单接口进行压测,但目前想模拟完成多接口同时压测,还需要再改造一下,之前我们想到,crank目前只能完成单独压测任务,那是不是有多个Agent,每个Agent单独压测一个接口,并同时启动多个Agent同时压测是不是可以模拟出来场景压测,那我通过批处理任务多点几次不同的接口压测不就可以了,基于以上考虑,又做了一个批处理脚本,用于调用多个接口的压测任务启动,最后的结构如下所示:</p> <pre><code>Crank ├─ benchmarks 压测脚本 │ ├─ api 接口压测脚本 │ │ ├─ add │ │ └─ get │ ├─ scipts lua脚本 │ │ ├─ common lua公共脚本 │ │ │ ├─ oauth.lua 认证lua脚本 │ │ │ ├─ util.lua lua工具类脚本 │ │ ├─ request.lua 封装请求lua脚本 │ ├─ scripts.tar lua脚本压缩包 ├─ common │ ├─ load.profiles.yml agent 负载机配置 │ ├─ project.profiles.yml 项目配置 │ ├─ scripts.profiles crank 执行script配置,用于对输出结果的二次处理 │ ├─ project.profiles.yml 项目配置 ├─ scripts 场景压测脚本 │ ├─ 用户.bat 用户压测 └─ env 环境配置,标记当前需要压测的环境在哪个配置文件中存储 └─ env.local 本地环境,存储本地环境的配置信息 └─ README.md 帮助文档 </code></pre> <h2>4. 结尾</h2> <p>通过上面的操作我们已经完成了对单接口以及单场景的压测,通过控制台可以清晰的看到每个接口的压测结果,我们只需要耐心等待压测任务结束,并整理压测结果数据,最后进行汇总我们的任务就完成了,但压测结果的收集也是一个费事费力的工作,作为一个开发,是不想把时间花费到这些整理表格的事情上,那我们如何做可以把整理表格数据的工作节省下来让我们可以歇会儿呢……</p> <p>源码地址:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Ftree%2Fsample%2Fsamples%2Fwrk2" target="_blank">https://github.com/doddgu/crank/tree/sample/samples/wrk2</a></p> <p>参考链接:</p> <ul> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fxinzhao%2Fp%2F6233009.html" target="_blank">https://www.cnblogs.com/xinzhao/p/6233009.html</a></li> </ul> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192888697174
4. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识wrk、wrk2 https://www.v2tn.com/content/1685192870747705 <h2>1. 前言</h2> <p>上一篇文章我们了解了bombardier,并知道了bombardier.yml与开源项目bombardier的关系,接下来的文章我们了解一下wrk、wrk2,并对比一下它们与bombardier的关系</p> <h2>2. 认识wrk</h2> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fwg%2Fwrk" target="_blank">wrk</a>是一种现代 HTTP 基准测试工具,能够在单个多核 CPU 上运行时产生大量负载。它结合了多线程设计和可扩展的事件通知系统,例如 epoll 和 kqueue。</p> <p>其支持参数:</p> <pre><code>-c, --connections: total number of HTTP connections to keep open with each thread handling N = connections/threads -d, --duration: duration of the test, e.g. 2s, 2m, 2h -t, --threads: total number of threads to use -s, --script: LuaJIT script, see SCRIPTING -H, --header: HTTP header to add to request, e.g. "User-Agent: wrk" --latency: print detailed latency statistics --timeout: record a timeout if a response is not received within this amount of time. </code></pre> <p>基础用法:</p> <blockquote> <p>运行了30秒的基准测试, 使用2个线程、100个http连接:</p> </blockquote> <pre><code>wrk -t2 -c100 -d30s http://127.0.0.1:8080/index.html </code></pre> <p>进阶用法:</p> <blockquote> <p>每次发送三个http请求:</p> </blockquote> <pre><code>wrk -t2 -c100 -d30s --script ./pipeline.lua http://127.0.0.1:8080 </code></pre> <p>新建pipeline.lua</p> <pre><code>-- example script demonstrating HTTP pipelining init = function(args) local r = {} r[1] = wrk.format(nil, "/?foo") r[2] = wrk.format(nil, "/?bar") r[3] = wrk.format(nil, "/?baz") req = table.concat(r) end request = function() return req end </code></pre> <h2>3. 认识wrk2</h2> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fgiltene%2Fwrk2" target="_blank">wrk2</a>是一个主要基于 wrk 的 HTTP 基准测试工具。是一个被 wrk 修改以产生恒定的吞吐量负载,并将延迟细节精确到高 9s(即当运行足够长的时间时可以产生准确的 99.9999%'ile)。除了 wrk 的参数之外,wrk2 通过 --rate 或 -R 参数(默认为 1000)采用吞吐量参数(每秒总请求数)</p> <p>除支持wrk的参数之外,还支持参数:</p> <pre><code>-R, --rate: 采用吞吐量参数(每秒总请求数),默认为1000 </code></pre> <p>基础用法:</p> <blockquote> <p>运行了30秒的基准测试, 使用2个线程、100个http连接、并保持每秒2000个请求的恒定吞吐量:</p> </blockquote> <pre><code>wrk -t2 -c100 -d30s -R2000 http://127.0.0.1:8080/index.html </code></pre> <p>高级用法与wrk一致,此处忽略不写</p> <p>我们使用wrk2测试一下百度的压测情况</p> <p><strong>安装:</strong></p> <pre><code>sudo apt install wget sudo wget https://aspnetbenchmarks.blob.core.windows.net/tools/wrk2 </code></pre> <p><strong>运行:</strong></p> <pre><code>./wrk2 -d 3s -c 200 -t 200 -R 10 -L https://www.baidu.com </code></pre> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2FC7rMyT5XDH3QK0GtCVAEpXfIp" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/C7rMyT5XDH3QK0GtCVAEpXfIp.svg" alt="asciicast"></a></p> <p>输出了本次请求每秒请求次数、吞吐量以及详细情况:</p> <ul> <li>Requests/sec: 每秒请求次数</li> <li>Transfer/sec: 每秒吞吐量</li> </ul> <h2>4. 了解Microsoft.Crank.Jobs.Wrk</h2> <p>在Microsoft.Crank.Jobs.Wrk项目中Program.cs</p> <ol> <li>检查平台是否是64位的Linux系统、并检查参数是否满足要求</li> <li>通过HttpClient发送请求,并记录第一次发送请求所消耗的时间</li> <li>下载wrk,并设置wrk是可执行的</li> <li>通过yml传递过来的参数构建完整的wrk命令</li> <li>将输出的结果使用追加到stringBuilder上,再赋值给output,</li> <li>通过正则匹配结果,最后通过BenchmarksEventSource存储并输出到控制台或数据库、csv、json中</li> </ol> <p>其中:</p> <ul> <li>connections: 每个线程处理时保持打开的 HTTP 连接总数 N = 连接数/线程数</li> <li>serverUri: 自定义url,如果此参数存在,则请求地址为: {serverUri}:{serverPort}{path}</li> <li>serverPort: 服务端口</li> <li>serverScheme: 服务的Scheme,默认http、支持http、https两种</li> <li>serverAddress: 服务地址、不包含http、例如: www.baidu.com,如果serverUri存在,此配置无效,如果不存在,请求格式为: {serverScheme}://{serverAddress}:{serverPort}{path}</li> <li>path: 服务接口地址,不包含域,例如: /api/check/healthy</li> <li>warmup: 预热时间,默认15s,与执行duration类似,而并非压测次数 <ul> <li>当warmup &gt; 0时,会先预热warmup秒后再执行一次压测,第二次的压测才是最后返回的结果</li> <li>当warmup = 0时,不进行预热,直接开始压测</li> </ul> </li> <li>duration: 测试时长,默认15s</li> <li>threads: 线程数、默认:32</li> <li>customHeaders: 自定义headers,如果预设headers中没有需要的header,则通过重写customHeaders,以完成自定义header的目的</li> <li>pipeline: 管道数量,默认为1,当大于1时,支持同时发送多个请求</li> <li>script: 如果pipeline不大于1时,支持自定义lua脚本以及lua参数{scriptArguments}</li> </ul> <h2>5. 总结</h2> <p>优势:</p> <ul> <li>支持lua脚本,支持动态参数或者更改请求等复杂操作</li> <li>使用C语言开发、性能高</li> </ul> <p>劣势:</p> <ul> <li>lua脚本存在学习成本</li> </ul> <blockquote> <p>wrk.yml的存在是为Microsoft.Crank.Jobs.Wrk提供配置参数,Microsoft.Crank.Jobs.Wrk通过调用开源项目wrk实现压测,并将压测结果通过BenchmarksEventSource存储并输出到控制台或数据库、csv、json中</p> </blockquote> <p>wrk2是基于wrk二次开发,拥有所有wrk的配置,并且支持吞吐量限制,bombardier、wrk、wrk2都是http基准测试工具,丰富了crank对于Http的基准测试能力,三者之间并无优劣之分,根据三者之间的优劣势自行选择适合自己的即可</p> <p>源码地址:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Ftree%2Fsample" target="_blank">https://github.com/doddgu/crank/tree/sample</a></p> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192870747705
3 步排查,3 步优化,探针性能损耗直降 44% https://www.v2tn.com/content/1685192832425375 <p>应用接探针除了安全问题,最担心的就是占用系统性能影响业务正常运转,今天分享一个实际案例告诉大家如何来降低探针的性能损耗。 下表为某用户的2条核心链路在200并发压测下的性能数据对比,可以看见在接入探针后性能损耗居高不下。 <img style='max-width:100%' src="https://img-blog.csdnimg.cn/4c22443977ca4f1d93a65e539a4b4e43.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述"></p> <h1>3步快速排查</h1> <h2>1.对比链路差异</h2> <p>首先想到的排查方案是通过skywalking监控进行排查,对比应用在接入探针和未接入探针的情况下,性能表现的差异在哪,具体的的性能消耗在哪个中间件。 在对比skywalking监控的链路耗时,确实可以观察到未接入探针比接入探针和链路的RT高,但是不清楚是否存在客户环境问题或者skywallking上的链路有断裂的问题,信息并不全面无法准确定位。 <img style='max-width:100%' src="https://img-blog.csdnimg.cn/ad26b5d4a6cb4886aa9bb5ee8a2662de.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/83963be167064d56a05c2c553f14400c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <h2>2.插件排除法</h2> <p>在无其它有效信息时,尝试通过排除法定位具体影响性能的插件。具体做法是先整理链路用到的中间件,先移除所有中间件插件,再逐一增加单个中间件插件,不断的进行压测,观察哪个插件对性能的影响比较大。依靠这个方法定位成功到dubbo与logback两个插件,它们对性能影响比较大。 <img style='max-width:100%' src="https://img-blog.csdnimg.cn/f13711661ea34f08aacebaca7e23a9ac.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <h2>3.性能数据收集</h2> <p>在压测测试的同时,我们在agent框架内增加了对中间件插件interceptor方法执行的耗时统计代码,这部分数据会统一输出到固定的日志文件中。此外我们开发了与之配套的性能日志分析程序,配合日志收集脚本,可以对整个链路的所有应用打印的性能数据进行分析,输出汇总出一份中间件interceptor的统计结果,这份结果可以直观的看到每个中间件的性能耗时占比。 <strong>统计结果样例:</strong> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/01e5abc4e66c4c57a2cbe55ca50fa877.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <p><strong>性能收集代码展示:</strong> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/9c312e3ea6e248dbbe028b39f42cda8b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <h1>3步具体优化</h1> <h2>1.减少切点</h2> <p>agent产生性能损耗的终归原因是因为agent增强中间件代码后,会修改目标类的字节码,植入一些额外的逻辑,正是这些额外的逻辑带来了额外的耗时。切点越多植入的逻辑越多,整个链路的损耗就可能越高,所以尽可能的减少切点的数量一定会减少性能损耗。 按照这个思路,我们将前面排查出来耗时占比较高的logback中间件进行了重新设计。原先logback的实现有三个切点,分别负责:影子appender的注册、流量标识、日志隔离,经过重新设计后,优化为一个切点实现所有功能。</p> <h2>2.静默&amp;业务流量过滤</h2> <p>尽管中间件插件的增强逻辑不尽相同,但agent在植入到目标类的字节码都是统一的。他们都有统一入口,前置的运行逻辑都是同一套框架,实际运行时序图如下: <img style='max-width:100%' src="https://img-blog.csdnimg.cn/b61dd7641c784d31aa4f35e6d50e98c2.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <p>实际上有很多Interceptor的增强逻辑只有压测流量时才会执行,可这部分interceptor的执行全部需要经过前面从Messager到AdviceListener的一系列调用,这是完全没有必要并且会带来一定的性能损耗。这种无用调用可以在最前端做个判断,从开始就过滤掉,在达到效果的同时降低性能损耗。 <img style='max-width:100%' src="https://img-blog.csdnimg.cn/69396383ca6948b99f323ea391d371be.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <p>为此我们对框架进行了改造,让类似这种interceptor能在最前端就把流量过滤掉,避免执行无意义的逻辑。同时在最前端增加了静默开关,静默开关可以一键禁用掉所有中间件增强逻辑的执行,一定程度上可以代替卸载操作。相比卸载来说它不会还原实际的字节码,也不会回收内存占用,但是会更加轻量级,响应更快,影响更小。 <strong>改造后的运行时序图:</strong> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/e843b3272d33420597a4e782c2e8fb94.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <h2>3.中断逻辑优化</h2> <p>对logback插件进行重新设计后产生了一定效果,但是从性能采集的数据来看,性能损耗占比最高的还是logback插件。经过反复斟酌发现logback本身已经没有在进一步优化的空间了,于是将目光转向了框架层面,最后将重点放在了优化CutoffInterceptor类型中断机制。 CutoffInterceptor是一个类似挡板的Interceptor,它可以中断源码本身的运行,并且支持对返回值替换。比如数据库隔离的实现,我们一般会实现一个CutoffInterceptor,在压测流量经过时返回影子数据库的connection代替业务connection,以实现数据的隔离。logback同样也是实现了一个CutoffInterceptor,在压测流量经过时返回影子的appender替换业务的appender实现日志隔离。 CutoffInterceptor内部的实现原理是通过异常机制实现的,在替换返回值时,实际上是抛出了一个异常由上层捕获,实现对源代码的中断。 <img style='max-width:100%' src="https://img-blog.csdnimg.cn/4a8048afebcf469485159a0645944a00.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/e63fab59aaee4199bf09446e3c9a0851.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/27e82256c3dc47bca78e1afc9423a47e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <p>众所周知,在java中通过抛出实现流程控制的效率其实是比较低的,我们内部测试验证也证实了这点,一个空逻辑的CutoffInterceptor和同样的一个空逻辑Interceptor的性能差距相差几十近百倍。恰好logback这种日志类型的中间件执行频率是非常高的,所以导致这块的性能损耗一直下不去。于是我们把CutoffInterceptor的中断机制进行了优化,抛出异常改为了先advice设置中断标记,再由上层判断去控制中断。</p> <p><img style='max-width:100%' src="https://img-blog.csdnimg.cn/354754493f9b4528a5e62c29364a3366.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/a9885ec08b324dd392318bef504fbced.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"> <img style='max-width:100%' src="https://img-blog.csdnimg.cn/30a91b7d3c8248acb471701553391475.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> <h1>最终结果</h1> <p>经过一系列的优化动作之后,两条核心链路的性能损耗都有了大幅度的提升,链路A性能损耗由48%下降至4%,链路B的性能损耗由35%下降至3.4%。</p> <p><img style='max-width:100%' src="https://img-blog.csdnimg.cn/2031ef7a8acf4edd9ca8ba1651e221e7.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pWw5YiX56eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述"></p> 数列科技 2023-05-27 https://www.v2tn.com/content/1685192832425375
阿里巴巴在开源压测工具 JMeter 上的实践和优化 https://www.v2tn.com/content/1685192803295262 <p><em>作者:灵苒、涧泉</em></p> <p>Apache JMeter <strong>[1]</strong> &nbsp;是 Apach 旗下的开源压测工具,创建于 1999 年初,迄今已有超过 20 年历史。JMeter 功能丰富,社区(用户群体)庞大,是主流开源压测工具之一。</p> <p>性能测试通常集中在新系统上线或大型活动前(如电商大促,春节活动等),以验证系统能力,帮助排查定位性能瓶颈等问题。</p> <p>一次压测活动可粗略分为几个步骤:</p> <ol> <li>场景配置。配置压测场景模拟用户(业务)与系统的交互。</li> <li>压测执行。按指定压力量级启动压测。</li> <li>压测监控分析。压测中通常关注施压 RPS,成功率,业务响应时间(RT),网络带宽等关键指标。</li> <li>报告总结。披露系统能力是否符合要求,同时沉淀记录系统性能演变和优化过程。</li> </ol> <h2>原生&nbsp;JMeter&nbsp;实施压测</h2> <p>在 JMeter 的 GUI 页面编辑压测脚本,点击开始按钮调试 JMeter 脚本,具体操作可参考&nbsp;JMeter官网 <strong>[1]</strong> 。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a07166c4cbf54037992f5820894698c4~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>对于场景简单,要求测试并发量不高的情况下,JMeter 本地测试就能满足需求。但随着互联网用户的增加,对系统承载更大并发的需求日渐提升,而单台 JMeter 施压机的施压能力有一定上限,所以需要使用多台施压机,以提高 JMeter 的施压能力,这就要使用到 JMeter 的分布式施压功能。</p> <p>JMeter 的分布式压测需要用户自己管理维护多台机器,使用过程中注意以下几点:</p> <ul> <li>施压机的防火墙已关闭或打开了正确的端口。为 RMI 设置了 SSL 或禁用了它。</li> <li>所有施压机都在同一个子网上。如果使用 192.xxx 或 10.xxx IP 地址,则服务器位于同一子网中。</li> <li>所有施压机上使用相同版本的 JMeter 和 Java。</li> <li>所有施压机都已经拷贝了切分好的 CSV 数据文件、依赖 jar 包等。</li> <li>压测过程中需要监控施压机是否正常发流量,保持压力与配置一致。</li> <li>施压前配置好监控数据的收集,方便压测结束后报告的生成。</li> </ul> <p>由此可见 JMeter 的分布式压测需要协调各资源,前置准备以及施压过程维护施压引擎比较麻烦,对实施压测的人员来说压测效率低。</p> <h2>云上的&nbsp;JMeter&nbsp;实践</h2> <p>阿里巴巴有着非常丰富的业务形态,每一种业务形态背后都由一系列分布式的技术体系提供服务,随着业务的快速发展,特别是在双 11 等大促营销等活动场景下,准确评估整个业务站点的服务能力成为一大技术难题。</p> <p>在这个过程中,我们打造了自己的全链路压测系统,以应对更复杂、更多样的压测需求,并将此技术输出到 性能测试 PTS 上,同时支持原生 JMeter 压测。</p> <h3>通过控制台实践&nbsp;JMeter</h3> <h4>上传脚本</h4> <p>打开&nbsp;PTS 控制台 <strong>[2]</strong> 主页,左侧导航栏选择压测中心 &gt; 创建场景 &gt; JMeter 压测 ,新建 JMeter 压测场景。填写场景名,如 jmeter-test 。场景配置页面点击上传文件按钮,上传本地测试通过的 test.jmx 脚本。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e57e990b09e64f818de60d7cc636fd4e~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h4>施压配置</h4> <p>施压配置 页面,并发数设置为 50,压测时长设置为 2 分钟。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/813464662dc64942857f2030d73568f5~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h4>保存压测</h4> <p>点击保存去压测,弹出提示框点击确认,PTS 即开始在云端引擎执行 JMeter 脚本发起压力。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fdc62a27759742caa70c0451e4c0c032~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>压测中页面如下:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3ac15215f61e40adb41656b6ea667408~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>注意:因为机器配置和网络环境的差异(PTS 施压机默认为 4 核 8G,BGP 多线路公网),PTS 上压测结果可能与本地压测结果存在一定差异。另外,PTS 上的施压配置会覆盖原脚本中的配置,原脚本无论是写死固定配置还是使用 JMeter 属性配置都没关系。</p> <h3>通过&nbsp;OpenAPI&nbsp;实践&nbsp;JMeter</h3> <p>云计算会发展成像水电煤一样,成为社会的基础设施。OpenAPI 好比一条条快速管道,连接着企业和阿里云,把资源源源不断的输送给企业。使用云计算来构建 IT 基础设施是未来的发展趋势,这一点已经成为社会共识。OpenAPI 是云服务开放的重要窗口,没有 OpenAPI 的云服务将很难被客户的系统所集成,既影响了用户体验,也制约了云厂商本身的发展。同样的,在压测领域,随着压测需求日益多样化,更多用户希望将云上的压测能力继承到自己的系统,或者根据自己的业务系统,编排自定义的压测平台,从而实现自动化定制化压测需求。</p> <p>以下代码实现了使用 PTS 的 OpenAPI 一键启动 JMeter 压测场景,并且在完成压测后查看压测报告。</p> <h4>引入 pom 依赖</h4> <pre><code>&lt;!--创建PTS场景需要的实体类,如果只使用JMeter压测则不需要引入--&gt; &lt;dependency&gt; &lt;groupId&gt;com.aliyun&lt;/groupId&gt; &lt;artifactId&gt;pts-api-entity&lt;/artifactId&gt; &lt;version&gt;1.0.1&lt;/version&gt; &lt;/dependency&gt; &lt;!--PTS Java SDK依赖。--&gt; &lt;dependency&gt; &lt;groupId&gt;com.aliyun&lt;/groupId&gt; &lt;artifactId&gt;pts20201020&lt;/artifactId&gt; &lt;version&gt;1.8.10&lt;/version&gt; &lt;/dependency&gt; &lt;!--阿里云核心库。--&gt; &lt;dependency&gt; &lt;groupId&gt;com.aliyun&lt;/groupId&gt; &lt;artifactId&gt;aliyun-java-sdk-core&lt;/artifactId&gt; &lt;version&gt;4.5.2&lt;/version&gt; &lt;/dependency&gt; </code></pre> <h4>复制下列代码</h4> <pre><code>import com.aliyun.pts20201020.Client; import com.aliyun.pts20201020.models.*; import com.aliyun.teaopenapi.models.Config; import java.util.ArrayList; import java.util.List; import java.util.Map; public class StartingDemo { public static void main(String[] args) throws Exception { Client client = getClient(); // 创建场景 String sceneId = createScene(client); // 启动场景 String reportId = startTesting(client, sceneId); // 最多等待次数 int count = 0; // 查询是否已生成报告 while (!hasReport(client, reportId) &amp;&amp; count++ &lt; 20) { // 若报告还未生成,则等待(30s)一段时间再查询 // 根据压测时间酌情等待 Thread.sleep(30 * 1000); } // 查看报告 getJMeterReport(client, reportId); } private static boolean hasReport(Client client, String reportId) throws Exception { ListJMeterReportsRequest request = new ListJMeterReportsRequest(); // 分页设置 request.setPageNumber(1); request.setPageSize(1); // 查询条件设置 request.setReportId(reportId); ListJMeterReportsResponse response = client.listJMeterReports(request); return response.getBody().getReports().size() &gt; 0; } private static void getJMeterReport(Client client, String reportId) throws Exception { // 查看机器日志 GetJMeterLogsResponse getJMeterLogsResponse = getJMeterLogs(client, reportId); List&lt;Map&lt;String, ?&gt;&gt; logs = getJMeterLogsResponse.getBody().getLogs(); // 查看采样器聚合数据 GetJMeterSampleMetricsResponse getJMeterSampleMetrics = getJMeterSampleMetrics(client, reportId); List&lt;String&gt; sampleMetricList = getJMeterSampleMetrics.getBody().getSampleMetricList(); // 查看采样日志 GetJMeterSamplingLogsResponse getJMeterSamplingLogs = getJMeterSamplingLogs(client, reportId); List&lt;String&gt; sampleResults = getJMeterSamplingLogs.getBody().getSampleResults(); } private static GetJMeterSamplingLogsResponse getJMeterSamplingLogs(Client client, String reportId) throws Exception { GetJMeterSamplingLogsRequest request = new GetJMeterSamplingLogsRequest(); // 分页设置 request.setPageNumber(1); request.setPageSize(10); // 条件设置 request.setReportId(reportId); GetJMeterSamplingLogsResponse response = client.getJMeterSamplingLogs(request); return response; } private static GetJMeterSampleMetricsResponse getJMeterSampleMetrics(Client client, String reportId) throws Exception { GetJMeterSampleMetricsRequest request = new GetJMeterSampleMetricsRequest(); // 设置报告id request.setReportId(reportId); GetJMeterSampleMetricsResponse response = client.getJMeterSampleMetrics(request); return response; } private static GetJMeterLogsResponse getJMeterLogs(Client client, String reportId) throws Exception { GetJMeterLogsRequest request = new GetJMeterLogsRequest(); // 分页设置 request.setPageNumber(1); request.setPageSize(10); // 查询的压测引擎索引 request.setReportId(reportId); GetJMeterLogsResponse response = client.getJMeterLogs(request); return response; } private static String startTesting(Client client, String sceneId) throws Exception { StartTestingJMeterSceneResponse startTestingSceneResponse = startTestingScene(client, sceneId); String reportId = startTestingSceneResponse.getBody().getReportId(); return reportId; } private static StartTestingJMeterSceneResponse startTestingScene(Client client, String sceneId) throws Exception { StartTestingJMeterSceneRequest request = new StartTestingJMeterSceneRequest(); request.setSceneId(sceneId); StartTestingJMeterSceneResponse response = client.startTestingJMeterScene(request); return response; } private static String createScene(Client client) throws Exception { SaveOpenJMeterSceneRequest request = new SaveOpenJMeterSceneRequest(); // 定义场景 SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterScene scene = new SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterScene(); // 设置场景名 scene.setSceneName("test"); // 设置文件列表,包括JMeter脚本、JMeter压测依赖jar包、配置额度数据文件等 List&lt;SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList&gt; fileList = new ArrayList&lt;SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList&gt;(); // 设置文件的属性 需要设置文件的名称和文件公网可访问的oss地址 SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList testFile = new SaveOpenJMeterSceneRequest.SaveOpenJMeterSceneRequestOpenJMeterSceneFileList(); testFile.setFileName("baidu.jmx"); testFile.setFileOssAddress("https://pts-openapi-test.oss-cn-shanghai.aliyuncs.com/baidu.jmx"); fileList.add(testFile); scene.setFileList(fileList); // 设置场景并发,可设置为100万 scene.setConcurrency(1000000); // 设置引擎数量 说明:一台引擎最多能发500并发,最少1并发所以此处能设置的引擎数为[2,1000],另外引擎数量越多消耗vum越快 scene.setAgentCount(2000); // 设置压测持续时间 60s scene.setDuration(60); // 设置测试文件的名称,这个文件需包括在文件列表中 scene.setTestFile("baidu.jmx"); request.setOpenJMeterScene(scene); SaveOpenJMeterSceneResponse response = client.saveOpenJMeterScene(request); return response.getBody().getSceneId(); } private static Client getClient() throws Exception { // 填写自己的AK/SK String accessKeyId = "ak"; String accessKeySecret = "sk"; Config config = new Config(); config.setAccessKeyId(accessKeyId); config.setAccessKeySecret(accessKeySecret); Client client = new Client(config); return client; } } </code></pre> <h4>填写自己的 ak/sk</h4> <p>在上述代码的 getClient 中填写正确的 ak/sk</p> <h4>点击启动</h4> <p>点击 main 方法启动</p> <h3>通过插件实践&nbsp;JMeter</h3> <p>对于长期使用 JMeter 的用户来说,学习一款新的压测工具还是需要一定的时间成本。因此,PTS &nbsp;开发了一款 PTS-JMeter 插件,可帮助 JMeter 用户在不改变原来的压测行为下直接使用 PTS 的压测资源。用户几乎不感知 PTS-JMeter 插件的存在,与原生 JMeter 使用方式一致,保存/打开 JMeter 脚本点击启动压测即可。</p> <h4>下载安装</h4> <p>点击链接下载最新版本 jar 包 <strong>[3]</strong></p> <p>将 jar 包拷贝到 JMeter 主目录下的 lib/ext 扩展目录下</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7c6eb16453cb497e8c9c4025ef2d8c24~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h4>点击压测</h4> <p>新建 JMeter 脚本,或者打开已有 JMeter 脚本,点击 PTS-JMeter 启动按钮开始压测</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f1bd438ed66247069cf59b7af7cf6e2b~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h4>查看报告</h4> <p>压测过程中,JMeter 图形界面会显示部分压测指标,用户可随时去控制台查看压测进程。压测结束后,PTS 会生成更加详细的压测报告,默认保留 30 天,用户可随时去控制台查看。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a75c16c7d1df448eb6078b3f04636250~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h4>其他</h4> <p>PTS-JMeter 插件更详细的使用方式可以去&nbsp;PTS 帮助文档 <strong>[4]</strong> 中查看。</p> <h2>压测监控分析</h2> <p>性能测试不仅仅是简单的发起压力,对压力负载(RPS,网络带宽等)和业务表现(RT,成功率等)的监控和分析也是压测活动的重要组成部分。JMeter 脚本中每个请求节点(Sampler)可设置一个具有业务含义的名字(如 home 和 download page ),我们可称之为业务 API 。JMeter 监控统计按业务 API 名字汇总,如两个名字相同的请求节点将汇总统计为一个业务 API 。配置脚本时需注意,不同业务 API 节点应配置为不同的名字。</p> <h3>业务 API&nbsp;压力负载和表现</h3> <p>实际工作中,不同业务 API 的统计数据可能存在巨大差异(如浏览商品 RT 通常比提交订单快很多),因此 PTS 默认将各个业务 API 独立统计展示(如上述压测中页面展示的 home 和 download page)。</p> <p>压测中每个时间点的数据 PTS 都在后台记录了下来,最终将形成完整直观的压测报告。点击业务 API 实时监控趋势图按钮 ,即可查看对应的 RPS,成功率,响应时间,网络带宽等监控数据的变化趋势图。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2a96c3305db1402d9f3900a40245b998~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3>业务 API 采样日志</h3> <p>很多时候我们还希望看到一个具体请求执行的详细信息。如有 1% 的请求失败,需要查看完整的请求、响应内容,以排查失败原因等。JMeter 图形界面下测试脚本时,可添加 View Results Tree 查看单个请求的详细信息,但执行压力测试时,对每个请求都记录详细信息,不仅没有必要,而且非常耗费资源,影响施压性能。</p> <p>阿里云 PTS 采取了一个折中的办法,施压引擎间隔一段时间对每个业务 API(压测Sampler)分别采样记录一条成功和失败(如果有)的请求详细信息。在压测中或压测报告页面,点击查看采样日志按钮即可查询记录的请求采样信息,并支持按业务 API(压测Sampler),响应状态(是否成功),请求时间等进行搜索过滤。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9f80c2474e404a73b606db56c0a44058~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>点击查看详情即可看到单个请求的详细信息。目前对详细信息提供了通用和 HTTP 两种展示模板,HTTP 展示模板可针对 HTTP 请求进行更友好的排版展示,展示内容包括请求 URL,请求方法,返回码,完整的请求头、请求体,响应头、响应体等。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/da49f4b9da95439c8267ee610f21a7cc~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>因为页面上只展示文本内容,请求体或响应体包含图片等无法识别为文本的内容时,可能显示为乱码。另外当请求体或响应体很大时,对应的内容可能被截断。</p> <h3>JMeter&nbsp;日志</h3> <p>本地执行 JMeter 脚本时,默认将日志记录到 jmeter.log 文件。在 PTS 上执行 JMeter 脚本时,可通过 JMeter 日志页面实时查看 JMeter 日志,并支持根据日志级别、时间或线程名进行查询过滤。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/498995682ba74137ac595291705e9c3d~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>JMeter 日志主要用于脚本执行报错时排查错误原因。一些插件可能通过 JMeter 日志输出一些重要信息,用户在 groovy 脚本等代码中也可以直接打印日志。</p> <h2>报告总结</h2> <p>压测结束后,PTS 将汇总监控数据形成压测报告。用户根据压测报告分析评估系统性能是否符合要求,如 RPS,成功率和 RT(响应时间)是否符合期望。并可辅助用户排查分析业务系统性能瓶颈。</p> <p>PTS 压测报告页面可查询历史压测报告列表。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1e49030b114940b3a1c13920a886060d~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>点击查看报告打开查看报告详情。压测报告在 PTS 上默认保存 30 天,可点击报告导出按钮,导出保存 PDF 版压测报告到本地。压测报告概要信息包括压测执行时间,RPS,RT,成功率等概要数据。场景详情包含全场景维度和业务 API 维度的监控统计信息。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/92635e9c06ec40918f90b5862bbdba0f~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>相比手动命令行执行 JMeter 脚本,PTS 更加简单易用,提供简单直观的监控,并提供海量施压能力 。</p> <h2>相关链接​</h2> <p>[1] Apache JMeter 官网:</p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fjmeter.apache.org%2F" target="_blank"></a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fjmeter.apache.org%2F" target="_blank">https://jmeter.apache.org/</a></p> <p>[2] PTS 控制台:</p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fpts.console.aliyun.com%2F%3Fspm%3D5176.7946858.J_5253785160.4.56a62d61PCy4nU%23%2Foverviewpage" target="_blank"></a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fpts.console.aliyun.com%2F%3Fspm%3D5176.7946858.J_5253785160.4.56a62d61PCy4nU%23%2Foverviewpage" target="_blank">https://pts.console.aliyun.com/?spm=5176.7946858.J_5253785160.4.56a62d61PCy4nU#/overviewpage</a></p> <p>[3] 点击链接下载最新版本 jar 包:</p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fpts.console.aliyun.com%2F%23%2Foverviewpage" target="_blank"></a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fpts.console.aliyun.com%2F%23%2Foverviewpage" target="_blank">https://pts.console.aliyun.com/#/overviewpage</a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fjmeter-pts-testing-version.oss-cn-shanghai.aliyuncs.com%2Fplugins%2FAlibabaCloud-PTS-JMeter-Plugin-1.1.jar%3Fspm%3Da2c4g.11186623.0.0.4ddc5993bpuaw4%26file%3DAlibabaCloud-PTS-JMeter-Plugin-1.1.jar" target="_blank"></a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fjmeter-pts-testing-version.oss-cn-shanghai.aliyuncs.com%2Fplugins%2FAlibabaCloud-PTS-JMeter-Plugin-1.1.jar%3Fspm%3Da2c4g.11186623.0.0.4ddc5993bpuaw4%26file%3DAlibabaCloud-PTS-JMeter-Plugin-1.1.jar" target="_blank"></a><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fjmeter-pts-testing-version.oss-cn-shanghai.aliyuncs.com%2Fplugins%2FAlibabaCloud-PTS-JMeter-Plugin-1.1.jar%3Fspm%3Da2c4g.11186623.0.0.4ddc5993bpuaw4%26file%3DAlibabaCloud-PTS-JMeter-Plugin-1.1.jar" target="_blank">https://jmeter-pts-testing-version.oss-cn-shanghai.aliyuncs.com/plugins/AlibabaCloud-PTS-JMeter-Plugin-1.1.jar?spm=a2c4g.11186623.0.0.4ddc5993bpuaw4&amp;file=AlibabaCloud-PTS-JMeter-Plugin-1.1.jar</a></p> <p>[4]&nbsp; PTS 帮助文档:​<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fhelp.aliyun.com%2Fdocument_detail%2F379921.html" target="_blank">​</a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fhelp.aliyun.com%2Fdocument_detail%2F379921.html" target="_blank"></a></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fhelp.aliyun.com%2Fdocument_detail%2F379921.html" target="_blank">​</a><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fhelp.aliyun.com%2Fdocument_detail%2F379921.html" target="_blank">​https://help.aliyun.com/document_detail/379921.html​</a>​</p> <p>​​</p> 阿里云云原生 2023-05-27 https://www.v2tn.com/content/1685192803295262
3. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识bombardier https://www.v2tn.com/content/1685192773227158 <h2>1. 前言</h2> <p>通过之前的学习,我们已经了解了各参数以及配置的意义,接下来的文章我们分别从bombardier以及wrk入手,进一步了解彼此之间的联系</p> <h2>2. 认识 bombardier</h2> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fcodesenberg%2Fbombardier" target="_blank">bombardier</a> 是一个 HTTP(S) 基准测试工具。它是用 Go 编程语言编写的,并使用优秀的fasthttp代替 Go 的默认 http 库,因为它具有闪电般的快速性能,<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fpkg.go.dev%2Fgithub.com%2Fcodesenberg%2Fbombardier%3Futm_source%3Dgodoc" target="_blank">详细文档查看</a></p> <p>其支持参数:</p> <pre><code>-c, --connections=125 Maximum number of concurrent connections -t, --timeout=2s Socket/request timeout -l, --latencies Print latency statistics -m, --method=GET Request method -b, --body="" Request body -f, --body-file="" File to use as request body -s, --stream Specify whether to stream body using chunked transfer encoding or to serve it from memory --cert="" Path to the client's TLS Certificate --key="" Path to the client's TLS Certificate Private Key -k, --insecure Controls whether a client verifies the server's certificate chain and host name -H, --header="K: V" ... HTTP headers to use(can be repeated) -n, --requests=[pos. int.] Number of requests -d, --duration=10s Duration of test -r, --rate=[pos. int.] Rate limit in requests per second --fasthttp Use fasthttp client --http1 Use net/http client with forced HTTP/1.x --http2 Use net/http client with enabled HTTP/2.0 -p, --print=&lt;spec&gt; Specifies what to output. Comma-separated list of values 'intro' (short: 'i'), 'progress' (short: 'p'), 'result' (short: 'r'). Examples: * i,p,r (prints everything) * intro,result (intro &amp; result) * r (result only) * result (same as above) -q, --no-print Don't output anything -o, --format=&lt;spec&gt; Which format to use to output the result. &lt;spec&gt; is either a name (or its shorthand) of some format understood by bombardier or a path to the user-defined template, which uses Go's text/template syntax, prefixed with 'path:' string (without single quotes), i.e. "path:/some/path/to/your.template" or "path:C:\some\path\to\your.template" in case of Windows. Formats understood by bombardier are: * plain-text (short: pt) * json (short: j) </code></pre> <p>并且bombardier支持多平台,可以在Windows、Linux、OSX系统上运行,那接下来我们使用bombardier测试一下百度的压测情况</p> <p><strong>安装(WSL-Ubuntu):</strong></p> <pre><code>sudo apt install wget sudo wget https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-linux-arm64 </code></pre> <p>运行:</p> <pre><code>./bombardier-linux-arm64 -c 200 -d 1s --insecure -l https://www.baidu.com --print r --format json </code></pre> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2FUz2fTLkoBmIVD8Xc7HwQqJAqg" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/Uz2fTLkoBmIVD8Xc7HwQqJAqg.svg" alt="asciicast"></a></p> <p>其中:</p> <ul> <li>req1xx代表http响应码为1**</li> <li>req2xx代表http响应码为2**</li> <li>req3xx代表http响应码为3**</li> <li>req4xx代表http响应码为4**</li> <li>req5xx代表http响应码为5**</li> <li>result.rps.mean代表每秒请求数</li> <li>result.rps.max代表每秒最大请求数</li> <li>result.latency.mean代表每毫秒延迟</li> <li>result.latency.max代表每毫秒最大延迟</li> </ul> <h2>3. 了解Microsoft.Crank.Jobs.Bombardier</h2> <p>在Microsoft.Crank.Jobs.Bombardier项目中Program.cs</p> <ol> <li>根据参数获取-w、-d、-n、-f参数信息</li> <li>校验压测时长、请求数等参数信息</li> <li>判断当前运行环境是Windows、Linux、OSX,根据环境下载对应的bombardier,并根据传递的</li> <li>根据yml参数最后拼装bombardier的原始命令:</li> </ol> <blockquote> <p>bombardier -c 200 -d 1s --insecure -l <a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.baidu.com" target="_blank">https://www.baidu.com</a> --print r --format json</p> </blockquote> <ol start="5"> <li>将输出的结果使用追加到stringBuilder上,再赋值给output</li> <li>通过JObject.Parse解析指标,最后通过BenchmarksEventSource存储并输出到控制台或数据库、csv、json中</li> </ol> <p>其中</p> <ul> <li>请求总数 = req1xx + req2xx + req3xx + req4xx + req5xx + others</li> <li>成功请求数 = req2xx + req3xx</li> <li>失败请求数 = 请求总数 - 成功请求数</li> </ul> <pre><code>BenchmarksEventSource.Register("bombardier/requests;http/requests", Operations.Max, Operations.Sum, "Requests", "Total number of requests", "n0"); BenchmarksEventSource.Register("bombardier/badresponses;http/requests/badresponses", Operations.Max, Operations.Sum, "Bad responses", "Non-2xx or 3xx responses", "n0"); BenchmarksEventSource.Register("bombardier/latency/mean;http/latency/mean", Operations.Max, Operations.Avg, "Mean latency (us)", "Mean latency (us)", "n0"); BenchmarksEventSource.Register("bombardier/latency/max;http/latency/max", Operations.Max, Operations.Max, "Max latency (us)", "Max latency (us)", "n0"); BenchmarksEventSource.Register("bombardier/rps/mean;http/rps/mean", Operations.Max, Operations.Sum, "Requests/sec", "Requests per second", "n0"); BenchmarksEventSource.Register("bombardier/rps/max;http/rps/max", Operations.Max, Operations.Sum, "Requests/sec (max)", "Max requests per second", "n0"); BenchmarksEventSource.Register("bombardier/throughput;http/throughput", Operations.Max, Operations.Sum, "Read throughput (MB/s)", "Read throughput (MB/s)", "n2"); BenchmarksEventSource.Register("bombardier/raw", Operations.All, Operations.All, "Raw results", "Raw results", "json"); var total = document["result"]["req1xx"].Value&lt;long&gt;() + document["result"]["req2xx"].Value&lt;long&gt;() + document["result"]["req3xx"].Value&lt;long&gt;() + document["result"]["req3xx"].Value&lt;long&gt;() + document["result"]["req4xx"].Value&lt;long&gt;() + document["result"]["req5xx"].Value&lt;long&gt;() + document["result"]["others"].Value&lt;long&gt;(); var success = document["result"]["req2xx"].Value&lt;long&gt;() + document["result"]["req3xx"].Value&lt;long&gt;(); BenchmarksEventSource.Measure("bombardier/requests;http/requests", total); BenchmarksEventSource.Measure("bombardier/badresponses;http/requests/badresponses", total - success); BenchmarksEventSource.Measure("bombardier/latency/mean;http/latency/mean", document["result"]["latency"]["mean"].Value&lt;double&gt;()); BenchmarksEventSource.Measure("bombardier/latency/max;http/latency/max", document["result"]["latency"]["max"].Value&lt;double&gt;()); BenchmarksEventSource.Measure("bombardier/rps/max;http/rps/max", document["result"]["rps"]["max"].Value&lt;double&gt;()); BenchmarksEventSource.Measure("bombardier/rps/mean;http/rps/mean", document["result"]["rps"]["mean"].Value&lt;double&gt;()); BenchmarksEventSource.Measure("bombardier/raw", output); var bytesPerSecond = document["result"]["bytesRead"].Value&lt;long&gt;() / document["result"]["timeTakenSeconds"].Value&lt;double&gt;(); // B/s to MB/s BenchmarksEventSource.Measure("bombardier/throughput", bytesPerSecond / 1024 / 1024); </code></pre> <h2>4. 解读bombardier.yml各参数作用</h2> <ul> <li>connections: 最大并发连接数,默认: 256</li> <li>warmup: 预热时间,默认15s,与执行duration类似,而并非压测次数 <ul> <li>当warmup &gt; 0时,会先预热warmup秒后再执行一次压测,第二次的压测才是最后返回的结果</li> <li>当warmup = 0时,不进行预热,直接开始压测</li> </ul> </li> <li>duration: 测试时长,单位: s</li> <li>requests: 请求数</li> <li>rate: 每秒请求数限制</li> <li>transport: 传输方式。默认: fasthttp 、支持fasthttp、http1、http2三种</li> <li>presetHeaders: 预设header,根据全局参数headers,自选其一即可,选择json,那请求的header即为: --header "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,<em>/</em>;q=0.7" --header "Connection: keep-alive"</li> <li>customHeaders: 自定义headers,如果预设headers中没有需要的header,则通过重写customHeaders,以完成自定义header的目的</li> <li>serverUri: 自定义url,如果此参数存在,则请求地址为: {serverUri}:{serverPort}{path}</li> <li>serverPort: 服务端口</li> <li>serverScheme: 服务的Scheme,默认http、支持http、https两种</li> <li>serverAddress: 服务地址、不包含http、例如: www.baidu.com,如果serverUri存在,此配置无效,如果不存在,请求格式为: {serverScheme}://{serverAddress}:{serverPort}{path}</li> <li>path: 服务接口地址,不包含域,例如: /api/check/healthy</li> <li>bodyFile: body内容,仅在非Get请求时使用,支持远程路径与本地绝对路径(Agent服务的绝对地址,非Controller端的绝对地址)</li> <li>verb: 请求方式: 默认GET、支持POST、PUT、DELETE、PATCH、GET</li> </ul> <h2>5. 总结</h2> <p>优势:</p> <ul> <li>跨平台</li> <li>用法简单</li> <li>使用go语言开发、性能高</li> </ul> <p>劣势:</p> <ul> <li>不支持动态参数</li> <li>不支持多个接口同时压测</li> </ul> <blockquote> <p>bombardier.yml的存在是为Microsoft.Crank.Jobs.Bombardier提供配置参数,Microsoft.Crank.Jobs.Bombardier通过调用开源项目bombardier实现压测,并将压测结果通过BenchmarksEventSource存储并输出到控制台或数据库、csv、json中</p> </blockquote> <p>源码地址:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Ftree%2Fsample" target="_blank">https://github.com/doddgu/crank/tree/sample</a></p> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192773227158
2. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识yml https://www.v2tn.com/content/1685192745396591 <h2>1. 前言</h2> <p>入门篇我们已经成功运行hello.benchmarks.yml并输出测试结果,本篇我们就hello.benchmarks.yml、以及运行的shell脚本详细解读下其中的含义</p> <h2>2. 剖析hello.benchmarks.yml</h2> <h3>2.1. job</h3> <ul> <li>在hello.benchmarks.yml中我们定义了一个新的job: server,并指定了仓库信息 ( 远程仓库 ):</li> </ul> <pre><code> repository:https://github.com/doddgu/crank.git # 仓库源 branchOrCommit:sample # 分支 project: samples/hello/hello.csproj # 项目 </code></pre> <ul> <li>并通过import导入了bombardier.yml,其中定义了另外一个job: bombardier,并指定了仓库信息 ( 远程仓库 ):</li> </ul> <pre><code> repository: https://github.com/doddgu/crank.git branchOrCommit: sample project: src/Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj sourceKey: bombardier # 服务器使用它来重用相同的源文件夹。 noBuild: true # 定义 SourceKey时,指示是否仍应进行构建 </code></pre> <h3>2.2. scenarios</h3> <ul> <li>在hello.benchmarks.yml中我们定义了场景: hello,并为此场景指定了两个任务: <ul> <li>第一个任务名为application,使用的是项目server</li> <li>第二个任务名为load,并指定使用项目bombardier</li> </ul> </li> </ul> <h3>2.3. variables 变量</h3> <ul> <li> <p>在bombardier.yml中</p> <ul> <li>定义了全局变量: headers、presetHeaders(预设header)</li> <li>定义了局部变量: connections、warmup、duration、requests、rate、transport、serverScheme等等</li> </ul> </li> <li> <p>在hello.benchmarks.yml中为load定义了局部变量serverPort、path</p> </li> </ul> <h3>2.4. profiles 配置</h3> <ul> <li>在hello.benchmarks.yml中我们 <ul> <li>定义了配置local</li> <li>并指定了局部变量: serverAddress = localhost</li> <li>为任务application、load指定了部署作业的endpoint 是 <a href="https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Flocalhost%3A5010" target="_blank">http://localhost:5010</a> (指定执行任务的Agent地址)</li> </ul> </li> </ul> <h3>2.5. arguments 参数</h3> <ul> <li>在bombardier.yml中与variables同级的配置: arguments,此参数是在启动job后传递的参数,其中定义的全局参数、局部参数信息也都是为构建完整的参数做准备,bombardier真实的参数信息是:</li> </ul> <pre><code>-c {{connections}} -w {{warmup}} -d {{duration}} -n {{requests}} --insecure -l {% if rate != 0 %} --rate {{ rate }} {% endif %} {% if transport %} --{{ transport}} {% endif %} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} {% if serverUri == blank or serverUri == empty %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} {% else %} {{serverUri}}:{{serverPort}}{{path}} {% endif %} {% if bodyFile != blank and bodyFile != empty %} -f {{bodyFile}} {% endif %} {% if verb != blank and verb != empty %} -m {{verb}} {% endif %} </code></pre> <h2>3. 改造hello.benchmarks.yml</h2> <p>改造hello.benchmarks.yml,不考虑重用,最原始的代码如下</p> <pre><code>variables: headers: none: '' plaintext: '--header "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"' html: '--header "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" --header "Connection: keep-alive"' json: '--header "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"' connectionclose: '--header "Connection: close"' presetHeaders: none jobs: bombardier: source: repository: https://github.com/dotnet/crank.git branchOrCommit: main project: src/Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj sourceKey: bombardier noBuild: true readyStateText: Bombardier Client waitForExit: true variables: connections: 256 warmup: 15 duration: 15 requests: 0 rate: 0 transport: fasthttp # | http1 | http2 serverScheme: http serverAddress: localhost serverPort: 5000 path: bodyFile: # path or url for a file to use as the body content verb: # GET when nothing is specified customHeaders: [ ] # list of headers with the format: '&lt;name1&gt;: &lt;value1&gt;', e.g. [ 'content-type: application/json' ] arguments: "-c {{connections}} -w {{warmup}} -d {{duration}} -n {{requests}} --insecure -l {% if rate != 0 %} --rate {{ rate }} {% endif %} {% if transport %} --{{ transport}} {% endif %} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} {% if serverUri == blank or serverUri == empty %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} {% else %} {{serverUri}}:{{serverPort}}{{path}} {% endif %} {% if bodyFile != blank and bodyFile != empty %} -f {{bodyFile}} {% endif %} {% if verb != blank and verb != empty %} -m {{verb}} {% endif %}" onConfigure: # - job.timeout = Number(job.variables.duration) + Number(job.variables.warmup) + 10; endpoints: - http://localhost:5010 server: source: repository: https://github.com/doddgu/crank branchOrCommit: sample project: samples/hello/hello.csproj readyStateText: Application started. endpoints: - http://localhost:5010 scenarios: hello: application: job: server load: job: bombardier variables: serverPort: 5000 path: / </code></pre> <h2>4. 解读crank shell</h2> <p>之前我们通过shell执行:</p> <ul> <li> <p>crank --config hello.benchmarks.yml --scenario hello --profile local --load.framework net5.0 --application.framework net5.0</p> <ul> <li>其中crank 是固定的、代表:Crank Controller</li> <li>--config:固定的配置,指执行哪个yml配置,每次仅能指定一个yml配置</li> <li>--scenario:固定的配置,设置场景是hello</li> <li>--profile:固定的配置,非必选,可多次设置,指定当前Crank命令申请的配置是local,使用local下配置的所有信息</li> <li>--load.framework: 格式:&lt;任务名&gt;.framework,为任务load指定framework的运行框架版本是net5.0、--application.framework同理</li> </ul> </li> <li> <p>改造hello.benchmarks.yml,因为移除了profile,所以执行: crank --config hello.yml --scenario hello --load.framework net5.0 --application.framework net5.0 即可</p> </li> </ul> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank%2Ftree%2Fmain%2Fsrc%2FMicrosoft.Crank.Controller" target="_blank">查看crank更多文档</a></p> <h2>5. 疑问</h2> <ul> <li>为什么启动crank时要增加--application.framework net5.0? <ul> <li>安装crank要求必须有net5.0的环境,所以指定net5.0不需要再单独安装框架环境</li> </ul> </li> <li>为什么启动crank时不指定framework时默认是netcore3.1呢? <ul> <li>使用记事本打开hello.csproj、Microsoft.Crank.Jobs.Bombardier.csproj 即可了解</li> </ul> </li> <li>scenarios节点下application以及load两个节点名称可以更换吗?只能有两个节点? <ul> <li>节点名称不固定,可以更换,也没有限制必须是两个节点,具体多少个节点根据自己的需要来</li> </ul> </li> </ul> <h2>6. 结尾</h2> <p>通过上面的学习,我们也已经完全的了解了各配置的作用,但对bombardier.yml与开源项目bombardier存在什么样的联系还不清楚,以及为什么叫做bombardier.yml而不是其他名字,并且是如何实现性能指标的输出,接下来就会讲到bombardier.yml与开源项目bombardier的关系,以及wrk.yml与wrk的关系</p> <p>源码地址:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Ftree%2Fsample" target="_blank">https://github.com/doddgu/crank/tree/sample</a></p> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192745396591
干货|一次完整的性能测试,测试人员需要做什么? https://www.v2tn.com/content/1685192704414706 <h1>作者介绍</h1> <p>邓宝菊(Kiki Deng),10年软件测试经验,4年团队管理经验,当前任职研发部架构质量工程部,整体负责研发部测试团队的效能、工具流程建设和人才培养。</p> <h1>前言</h1> <p>一、 <strong>规范性能测试实施流程的意义</strong></p> <p>规范的性能测试实施流程能够加强测试工作流程控制,明确性能测试各阶段应完成的工作,指导测试人员正确、有序的开展性能测试工作,提高各角色在性能能测试中的工作效率。本次分享的性能测试实施流程是性能测试开展的”指导方针”,希望帮助您可以早日成为性能测试”达人”。</p> <p>二、 <strong>性能测试实施流程</strong></p> <p>性能测试流程分为五个阶段,分别是【需求调研阶段】→【测试准备阶段】→【测试执行阶段】→【测试报告阶段】→【测试总结阶段】。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/297c8bfbc4f44b44a8dfaf9acbcc2037~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>每个阶段做什么事情?重点关注什么?</strong></p> <p><strong>1.需求调研阶段</strong></p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bb63532011ae45958c2acc719fad7f1d~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>正文</p> <h2>1.1. <strong>阶段概述</strong></h2> <p>调研阶段的主要工作为:组建工作小组、项目创建、需求分析、模型构建、定制性能测试详细实施计划。</p> <p>重点关注:需求调研、需要分析、模型构建</p> <h2>1.2. <strong>关键点描述</strong></h2> <p>需求调研分为两个步骤进行:需求调研、需求分析。</p> <p>该工作是性能测试<strong>必须的工作环节</strong>。工作产出文件为《XX项目性能测试需求表》,如:《云智慧_XXX系统_XXX模块性能测试需求表》。</p> <p>此阶段模型构建主要是业务模型构建。</p> <h3><strong>1.2.1需求调研</strong></h3> <p>Ø 需求调研工作由性能测试实施人员牵头负责,产品经理、开发工程师、运维工程师配合完成;</p> <p>Ø 需求调研的主要内容为:</p> <p>n 系统线上环境的性能需求,例如性能需求、可靠性需求、可维护性需求等;</p> <p>n 与系统性能需求相关的其它信息,包括系统信息(如线上环境硬件、参数配置、系统架构与部署方式、关联系统部署等)、业务信息(关键业务逻辑与处理流程、交易列表、交易量信息、业务分布规律等)、生产问题、文档资料等方面,并对收集到的信息进行汇总整理,实现对待测系统业务与技术的整体了解;</p> <p>Ø 开发项目组、需求部门、运维部门等测试任务提出方应填写《云智慧_XXX系统_XXX模块性能测试需求表》中的“任务信息”和“测试背景”等信息,提出的测试需求,简单文字不能说明的,可附加文件;</p> <p>Ø 性能测试小组的实施人员将调研获取的其它内容填入《云智慧_XXX系统_XXX模块性能测试需求表》;</p> <p>Ø 对于新立项系统或系统新开发版本,《云智慧_XXX系统_XXX模块性能测试需求表》应与《需求规格说明书》中的性能需求相一致。</p> <h3><strong>1.2.2需求分析</strong></h3> <p>Ø 需求分析的基本流程是:</p> <p>n 首先,由性能测试工程师根据需求调研所获取的信息进行分析,将《云智慧_XXX系统_XXX模块性能测试需求表》中的性能需求转换为具体的性能<strong>需求指标值</strong>;</p> <p>n 其次,根据测试环境与线上环境的差异分析,由性能测试工程师将线上环境条件下的性能需求指标值转换为本次测试环境条件下的性能<strong>需求指标值</strong>;</p> <p>例如:TPS(Transaction per Second):系统每秒处理交易数,推导过程如下,</p> <p>当前线上APP1.0试用系统主要为查询类交易,交易占比40%,系统生产交易量统计为1个月约20W笔,假设APP2.0系统上线后业务量激增到每日查询类20W,则每日总交易量T达到:</p> <p>T = 20W/40%=500000笔/日</p> <p>系统处理能力TPS推导:APP2.0上线后交易量最大500000笔/日,系统晚间几乎无交易量,按2:8原则推算,则(500000<em>80%)/(8</em>20%<em>3600)=69.4笔/秒,取整为70笔/秒,每年按业务量增长50%计算,则一年后系统处理能力指标约等于70+70</em>50%=105笔/秒。</p> <p>稳定性交易量推导: 取系统处理能力的60%_时长=105笔/秒*60%*8_3600=1814400笔。</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c5264eb45e154c8ba812335d706fd4dc~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>经过分析后汇总成测试指标值</p> <p>Ø 需求分析其主要内容和规范性要求如下:</p> <p>n 性能测试需求:应准确描述性能测试指标项及需求指标值。</p> <p>n 系统范围:应准确描述性能测试需求指标值所依托的测试范围信息,如应描述测试范围的关联系统逻辑示意图,及各关联系统的信息;在对系统局部环节进行测试时,也需阐明具体测试范围,详细描述被测系统的相关子系统。</p> <p>n 环境差异分析:应准确描述性能测试需求指标值所依托的测试环境信息,如须描述测试环境的总体网络拓扑结构图、测试环境机器配置表(数量、型号、资源、操作系统)、以及相应的软件配置、重要参数配置等。同时应准确描述线上环境的上述信息,并进行详细的环境差异性分析。</p> <p>以上分析内容将作为性能测试方案的重要组成部分。</p> <h3><strong>1.2.3模型构建例如:业务模型</strong></h3> <p>根据200X年XX月XX日~200X年XX月XX日期间的业务高峰日200X年XX月XX日的业务量统计,经过略微调整得出以下业务模型,要求业务模型交易至少占线上交易量的90%以上:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed4915eca30f4e398eba540e1c796611~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2><strong>2.测试准备阶段</strong></h2> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f9b4a31400ad48818d4536518d742bcf~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2><strong>2.1阶段概述</strong></h2> <p>测试准备阶段是性能测试工作中<strong>重要阶段</strong>。在准备阶段,需要完成业务模型到测试模型的构建、性能测试实施方案编写、测试环境的准备、性能测试案例设计、性能测试监控方案设计、性能测试脚本,及相关测试数据的准备,并在上述相关准备活动结束后按照测试计划进行准入检查。</p> <p>重点关注:测试模型构建、方案设计、案例设计、数据准备等</p> <h2><strong>2.2关键点描述</strong></h2> <h3><strong>2.2.1测试模型构建</strong></h3> <p>测试模型构建工作由性能测试实施人员完成;</p> <p>在需求分析的基础上,对调研收集到的相关资料与信息进行分析梳理,重点分析跨系统的交易路径、交易关联关系、数据的处理与流转、业务量、交易比例、典型交易,以及系统的处理能力等性能测试点,针对性地确定多个业务场景,并为每个场景选择一套具体的业务交易集,按照业务量比例构建相应的测试模型。</p> <p>本阶段的产出物为,各个测试场景,以及场景中典型交易及所占比率。</p> <p>例如:从业务模型到测试模型推导</p> <p>依据业务模型,通过与项目组及产品经理沟通,确定本次测试模型还需着重考虑以下内容:</p> <p>(1) 考虑到后期证券系统数据库升级,历史查询可能会影响,所以本次测试单独增加一个场景:历史委托和历史成交查询各50%(即0456和0457)。同时,考虑到线上环境绝大部分该交易是由总中心前置发起,所以本次测试“历史委托和历史成交查询”交易均采用从总中心发起;</p> <p>(2) 增加国债发行交易场景,国债发行认购日一般在柜台营业前进行,此场景只选择国债发行认购一支交易;</p> <p>(3) 同时,证券系统交易高峰时段柜员签到、柜员签退交易占比较小。</p> <p>通过以上分析得出本次测试模型有3个:一般交易日日间模型、国债发行日模型、以及历史查询交易模型。</p> <p><strong>一般交易日日间模型:</strong></p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8721552ad34b43f189fca00be10558c6~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>储蓄国债交易模型:</strong></p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1d14bd844b10493aacf6257d5b111682~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>历史查询交易模型:</strong></p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1e1fed5d15e426290690e5a502fed11~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3><strong>2.2.2方案设计</strong></h3> <p>性能测试实施方案编制是性能测试工作中必须的工作环节,其产出为《性能测试方案》,如:《云智慧_XXX项目_XXX功能模块_性能能测试方案V1.0.xlsb》。</p> <p>在方案中需要描述:测试需求、启停准则、测试模型设计、测试策略、测试内容、测试环境与工具需求,以及各个阶段的输出文档。在方案中还需说明性能测试工作的时间计划安排、预期的风险与风险规避方法等。测试模型设计内容来自本阶段测试模型设计中形成的测试场景,以及场景中典型交易及所占比率。</p> <h3><strong>2.2.3案例设计</strong></h3> <p>在案例设计中,包括案例的描述、测试环境描述(硬件、软件、应用版本、测试数据)、延迟设置、压力场景、执行描述、预期结果、监控要点。</p> <p>案例设计是性能测试工作的必须工作环节,案例设计的产出文件是《性能测试案例》。</p> <h3><strong>2.2.4数据准备</strong></h3> <p>环境准备工作中涉及到基础数据的准备。测试数据的数量、逻辑关系要求十分严格,测试基础数据的准备一般采用自造模拟数据或者使用脱敏后的线上数据。</p> <h3><strong>2.2.5测试脚本开发</strong></h3> <p>测试脚本开发工作就是发挥LR的时候。</p> <p>测试脚本是对业务操作的程序化体现,一个脚本一般为一项业务的过程描述。本活动主要为脚本的录制(编写)、修改和调试工作,从而保证在测试实施之前每个测试用例的脚本都能够在单笔和少量迭代次数的条件下能够正确执行。测试脚本开发的一般步骤如下:</p> <p>Ø 通过录制,或者编写,完成脚本代码生成。代码生成时,主要根据需求插入事务,作为测试过程中统计交易响应时间的单位;</p> <p>Ø 根据测试需求,进行参数化设置;</p> <p>Ø 设定检查点,根据报文内容字段判断交易是否正确执行,即检查点的设置在应用层面;</p> <p>Ø 根据测试要求确定是否设置集合点;</p> <h2>3.<strong>测试执行阶段</strong></h2> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/afb7ac7e2b314461b63992baaa3e0bd7~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2><strong>3.1阶段概述</strong></h2> <p>测试执行阶段是执行测试案例,获得系统处理能力指标数据,发现性能测试缺陷的阶段。测试执行期间,借助测试工具执行测试场景或测试脚本,同时配合各类监控工具。执行结束后统一收集各种结果数据进行分析。根据需要,执行阶段可进行系统的调优和回归测试。</p> <p>重点关注:结果记录、测试监控、结果分析</p> <h2><strong>3.2关键点描述</strong></h2> <h3><strong>3.2.1测试执行与结果记录</strong></h3> <p>测试执行过程有相应的优先级策略,依据测试案例的优先级别,优先执行级别较高的测试案例。测试过程中,通过对每个测试结果的分析来决定是重复执行当前案例还是执行新的测试案例;通常发现瓶颈问题会立即进行调整并重新执行测试用例,直到当前的案例通过。</p> <p>在执行阶段,测试的执行、分析调优、回归测试工作较为反复,须认真记录全部执行过程和执行结果,执行结果数据是分析瓶颈的主要依据。</p> <h3><strong>3.2.2测试监控</strong></h3> <p>测试的监控工作与执行工作同步进行,场景或脚本开始执行时,同时启动监控程序(可以用nmon或者系统命令top/vmstat/iostat 等),当然也可以用云智慧的监控宝和透视宝协同工作,监控宝可以监控网站/网页性能/Ping/DNS/FTP/UDP/TCP/SMTP等IT基础设施的性能指标,透视宝可以发现主机资源、Web应用、浏览器、APP等应用的性能瓶颈,如下图所示:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a585ea1cb5124b6d85b5fba0001c0066~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>监控宝监控页面</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b694b2838dc44dd5adaaf426468beddd~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>透视宝主机资源监控页面</p> <p>在执行结束后,停止测试监控,并提取监控结果数据。</p> <h3><strong>3.2.3测试结果分析</strong></h3> <p>测试过程中根据前端性能测试工具显示结果、监控结果综合分析出现的测试问题。</p> <p>例如:</p> <p>测试组在执行“一般日日间交易模型”负载测试570TPS压力时,数据库监控发现有死锁想象,具体如下:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/794310106c8347a5b82c0cdad26c7245~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>**问题分析:**经与开发一同分析,原因如下:流控信息收集程序(pltflowGthDaemon)在同一柜员、在毫秒级并发做交易时plt_flowgather表出现死锁。测试环境联机交易使用同一个柜员号发起,因此出现概率较高。</p> <h2><strong>4.测试报告阶段</strong></h2> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/70175b40ce58445da19fdc132330b5d7~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p><strong>4.1阶段概述</strong></p> <p>测试执行工作结束后开始撰写性能测试报告。性能测试报告在发布前需要进行评审。</p> <h2><strong>4.2关键点描述</strong></h2> <h3><strong>4.2.1报告撰写</strong></h3> <p>性能测试报告要内容包括:测试目的、范围及方法、环境描述、测试结果描述、结果分析、结论和建议等。</p> <h3><strong>4.2.2测试结果描述</strong></h3> <p>测试结果的描述,应体现性能测试的执行过程,如:混合场景的容量测试结果展示中,需要描述各个并发梯度下测试结果及监控结果;在数字形式的结果记录中,要求小数点后精确3位有效数字。</p> <h3><strong>4.2.3测试缺陷与问题</strong></h3> <p>在性能测试分析报告中须描述测试过程发现的缺陷与问题,对于确认是测试缺陷的项进行风险评估,并给出风险提示。</p> <h3><strong>4.2.4最终结果分析</strong></h3> <p>测试最终结果的分析,该部分内容应该全面、透彻、易理解且通过图表方式表达更直观。</p> <p>例如:</p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9e2829837a284f57b0b7ab3e08647945~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h3><strong>4.2.5测试结论</strong></h3> <p>测试结论是性能测试分析报告必须包括的内容。测试的结论须清晰、准确回答性能测试需求中描述的各项指标,需全面覆盖测试需求。</p> <h2><strong>5.测试总结阶段</strong></h2> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9a3a880e20174580a2ddf1d2995f1d5a~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <h2><strong>5.1阶段概述</strong></h2> <p>性能测试的总结工作,主要对该任务的测试过程和测试技术进行总结。性能测试工作进入总结阶段,也意味着性能测试工作临近结束。在这个阶段,时间允许的情况下应将所有的重要测试资产进行归档保存。</p> <h1>写在最后</h1> <p>近年来,在AIOps领域快速发展的背景下,IT工具、平台能力、解决方案、AI场景及可用数据集的迫切需求在各行业迸发。**基于此,云智慧在2021年8月发布了AIOps社区,**旨在树起一面开源旗帜,为各行业客户、用户、研究者和开发者们构建活跃的用户及开发者社区,共同贡献及解决行业难题、促进该领域技术发展。</p> <p><strong>社区先后<strong><strong>开源</strong></strong>了数据可视化编排平台-FlyFish、运维管理平台<strong><strong>OMP</strong></strong>、云服务管理平台-摩尔平台、<strong><strong>Hours</strong></strong>算法等产品。</strong></p> <p><strong>可视化编排平台-FlyFish:</strong></p> <p>项目介绍:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cloudwise.ai%2FflyFish.html" target="_blank">https://www.cloudwise.ai/flyFish.html</a></p> <p>Github地址: <a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FCloudWise-OpenSource%2FFlyFish" target="_blank">https://github.com/CloudWise-OpenSource/FlyFish</a></p> <p>Gitee地址: <a href="https://gitee.com/CloudWise/fly-fish">https://gitee.com/CloudWise/fly-fish</a></p> <p>行业案例:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2FBV1z44y1n77Y%2F" target="_blank">https://www.bilibili.com/video/BV1z44y1n77Y/</a></p> <p><strong>部分大屏案例:</strong></p> <p><img style='max-width:100%' src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a4fb35fd1c74da5b131152f9c457cf6~tplv-k3u1fbpfcp-zoom-1.image" alt=""></p> <p>您可以添加小助手(xiaoyuerwie)备注:飞鱼。加入开发者交流群,可与业内大咖进行1V1交流!</p> <p>也可通过小助手获取云智慧AIOps资讯,了解FlyFish最新进展!</p> 云智慧AIOps社区 2023-05-27 https://www.v2tn.com/content/1685192704414706
堪比JMeter的.Net压测工具 - Crank 入门篇 https://www.v2tn.com/content/1685192686750818 <h2>1. 前言</h2> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank" target="_blank">Crank</a> 是.NET 团队用来运行基准测试的基准测试基础架构,包括(但不限于)来自<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.techempower.com%2Fbenchmarks%2F" target="_blank">TechEmpower Web</a> 框架基准测试的场景,是2021年.NET Conf 大会上介绍的一项新的项目,其前身是<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Faspnet%2FBenchmarks" target="_blank">Benchmarks</a>。</p> <p>Crank目标之一是为开发人员提供一种工具,让他们能够非常轻松地处理性能并衡量潜在的改进。其中一些功能是:</p> <ul> <li>部署和基准测试基于 .NET 或 Docker 容器的多层应用程序</li> </ul> <blockquote> <p>通过指定.Net项目(本地路径或git远程仓库地址),支持直接部署或通过Docker部署应用程序,用于基准测试)</p> </blockquote> <ul> <li>通过Yml配置,不仅仅支持结果存储在 JSON 、SQL Server 中还支持存储到csv文件中以用于图表</li> </ul> <blockquote> <p>目前有小伙伴已经在提议将支持存储在<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank%2Fissues%2F366" target="_blank">es</a></p> </blockquote> <ul> <li>支持更改自定义应用程序的Franework环境,测试在不同环境下的性能</li> <li>收集诊断跟踪信息</li> </ul> <h2>2. 核心组成</h2> <p>Crank由Agent、Controller两部分组成</p> <p>Controller是任务的调度者,可以调度负载任务以及输出结果</p> <p>Agent是基准代理,任务的实际执行者,接收来自Controller的任务并执行。</p> <h2>3. 安装</h2> <p>欲先工其善 必先利其器,我们先学习下如何安装crank,以及如何验证是否安装成功</p> <h3>3.1. 准备工作</h3> <ol> <li> <p>安装 <a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fdotnet.microsoft.com%2Fdownload%2Fdotnet%2F5.0" target="_blank">.NET 5.0</a>.</p> </li> <li> <p>打开shell:安装Crank Controller</p> </li> </ol> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2Fkz2rcb0BZc94TPfdOgSdd9wdD" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/kz2rcb0BZc94TPfdOgSdd9wdD.svg" alt="asciicast"></a></p> <p>安装命令:</p> <pre><code>dotnet tool update Microsoft.Crank.Controller --version "0.2.0-alpha.21567.1" --global </code></pre> <p>验证命令:</p> <pre><code>crank </code></pre> <ol start="3"> <li>打开shell: 安装Crank Agent</li> </ol> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2FNvdronNl3GVJ7ZCMtXcLBcZ5B" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/NvdronNl3GVJ7ZCMtXcLBcZ5B.svg" alt="asciicast"></a></p> <p>安装命令:</p> <pre><code>dotnet tool update Microsoft.Crank.Agent --version "0.2.0-alpha.21567.1" --global </code></pre> <p>验证命令:</p> <pre><code>crank-agent </code></pre> <h3>3.2. 小结</h3> <p>为方便阅读、文章中Crank Controller简称Crank,Crank Agent简称Agent</p> <blockquote> <p>Agent以及Crank需要根据实际情况安装,可分以下几种情况:</p> <ul> <li> <p>只是为了学习Crank,没有单独的测试环境,则需要分别安装Agent、Controller</p> </li> <li> <p>Agent有单独提供测试环境,则本地不需要安装Agent,只安装Controller即可</p> </li> <li> <p>Agent有单独提供测试环境,且压测任务由ci来触发执行,则本地不需要安装任何配置,通过构建ci任务完成压力计划即可</p> </li> </ul> </blockquote> <p>打开shell:查看Agent、Controller版本</p> <pre><code>dotnet tool list -g </code></pre> <h2>4. 基础知识</h2> <h3>4.1. variables: 参数</h3> <p>variables分为局部参数与全局参数两种类型,在根节点的为全局参数,在其他节点下的是局部参数。</p> <p>例:</p> <p>hello.benchmarks.yml &gt; scenarios &gt; hello-load &gt; variables节点下的serverPort以及path以及profiles&gt;local&gt;variables节点下的serverAddress是局部参数</p> <pre><code>scenarios: hello: application: job: server load: job: bombardier variables: serverPort: 5000 path: / profiles: local: variables: serverAddress: localhost </code></pre> <p>bombardier.yml &gt; variables &gt; headers为全局参数</p> <pre><code>variables: headers: none: '' plaintext: '--header "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"' html: '--header "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" --header "Connection: keep-alive"' json: '--header "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"' connectionclose: '--header "Connection: close"' --------------------------------------------------------------------- </code></pre> <h3>4.2. profiles: 配置</h3> <p>profiles其实就是配置文件信息,profiles允许被多次使用,这点在可以在文档中找到对应<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank%2Ftree%2Fmain%2Fsrc%2FMicrosoft.Crank.Controller%23usage" target="_blank">介绍</a>。</p> <pre><code>Usage: crank [options] Options: -?|-h|--help Show help information These options are not specific to a Job ---------------------------------------------------------------------- --profile &lt;profile&gt; Profiles to apply. Can be used multiple times. </code></pre> <blockquote> <p>命名规则: 建议 *.profiles.yml</p> </blockquote> <h3>4.3. jobs: 任务</h3> <p>将我们要做的事定义为一个job。方便之后重用。此处的事指的是一类事,而不是指特定的某件事。</p> <p>例如:微软内置定义的bombardier就是一个job,这个job是通过<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fcodesenberg%2Fbombardier" target="_blank">bombardier</a>对其进行基准测试,并将结果记录并输出,而具体针对哪个接口进行基准测试其实并不关心。</p> <p>job根据应用程序源有分为远程、本地两种。</p> <p>本地源:</p> <pre><code>jobs: server: #任务名称,可根据任务作用自行命名 source: #任务源 localFolder: ../hello project: hello.csproj #要构建的 .NET 项目的文件名 readyStateText: Application started. #控制台中通知服务器它已启动的文本 </code></pre> <blockquote> <p>本地源localFolder针对当前运行crank --config执行命令所在的相对路径即可,任务开始后会将本地的项目发送到agent后再执行任务。</p> </blockquote> <p>远程源</p> <pre><code>jobs: server: source: repository: https://github.com/dotnet/crank branchOrCommit: main #远程源执行任务的分支 project: samples/hello/hello.csproj #要构建的 .NET 项目的文件名,格式:相对根的相对路径+项目名.csproj readyStateText: Application started. </code></pre> <blockquote> <p>远程源会将仓库信息发送到Agent,Agent会先将仓库下载下来并切换到指定的分支后再执行构建任务启动项目</p> </blockquote> <h3>4.4. scenarios: 场景</h3> <p>job关心的是一类事,而特定的事情并不关心,那具体的事是谁比较关心呢,没错那就是场景,也就是scenarios,scenarios通过多个job来完成对指定场景的基准测试,做的是具体任务的编排</p> <h3>4.5. imports: 导入</h3> <p>imports为我们提供了yml重用的可能,因为有imports的支持,我们才可以将公共的yml提取到一个单独的yml中,通过imports将使用到的yml导入即可,与js、css的导入有异曲同工之妙</p> <h3>4.6. 小结</h3> <blockquote> <p>在crank中,variables、profiles都不是必须的,但因为它们的存在,才使得我们可以以面向对象的思想开发,可以通过新增变量或指定配置完成基准测试,这块后面的实战中会有详细解释</p> </blockquote> <h2>5. 入门</h2> <p>经过之前的学习,我们对crank的基本配置也有了一定的了解,那接下来的时间,我们先试着学习下官方已经给我们准备好的Sample,下面的教程也会详细讲解一下各个配置的作用,希望能通过下面的学习了解到Crank的工作基本原理</p> <h3>5.1. 启动Agent</h3> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2Fj96YsyIFxgLmZkTTvLJnFfOYU" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/j96YsyIFxgLmZkTTvLJnFfOYU.svg" alt="asciicast"></a></p> <pre><code>crank-agent --dotnethome "/home/{your-account}/dotnet" </code></pre> <h5>5.1.0.1. 启动Agent并指定dotnet环境</h5> <ul> <li> <p>格式:crank-agent –dotnethome "dotnet安装地址"</p> </li> <li> <p>crank-agent --dotnethome "C:\Program Files\dotnet" (windows)</p> </li> <li> <p>crank-agent --dotnethome "/usr/share/dotnet" (Linux)</p> </li> </ul> <blockquote> <ul> <li> <p>在启动agent时,强烈建议大家增加dotnethome 配置,为agent运行指定环境,以免运行任务时由于环境问题而卡在<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank%2Fissues%2F354%23issuecomment-975657063" target="_blank">install sdk</a>这里</p> </li> <li> <p>因演示机器本地dotnet的使用的是安装路径为/home/gushoudao/dotnet,所以视频中运行的命令有所不同,这块还需要根据本地的实际情况自行调整路径即可 (因视频录制原因,在录制结束后会停止agent,我们真实使用中启动后不需要退出,一旦退出agent,就无法执行任务)</p> </li> </ul> </blockquote> <h5>5.1.0.2. 启动Agent并指定不清理临时文件</h5> <ul> <li>crank-agen --no-cleanup (指定不清理临时文件)</li> </ul> <blockquote> <p>默认agent执行任务结束后会删除当前任务执行过程中产生的临时文件</p> </blockquote> <h5>5.1.0.3. 启动Agent并指定构建任务的最大持续时间</h5> <ul> <li>crank-agent --build-timeout</li> </ul> <blockquote> <p>默认构建任务的最大持续时间为10 minutes</p> </blockquote> <p>更多配置<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Fblob%2Fsample%2Fsrc%2FMicrosoft.Crank.Agent%2FREADME.md" target="_blank">点击查看</a></p> <h3>5.2. 新建hello.benchmarks.yml配置</h3> <p>配置文件源码来自<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Fblob%2Fsample%2Fsamples%2Fhello%2Fhello.benchmarks.yml" target="_blank">hello.benchmarks.yml</a></p> <pre><code>imports: - https://raw.githubusercontent.com/doddgu/crank/sample/src/Microsoft.Crank.Jobs.Bombardier/bombardier.yml jobs: server: source: repository: https://github.com/doddgu/crank branchOrCommit: sample project: samples/hello/hello.csproj readyStateText: Application started. scenarios: hello: application: job: server load: job: bombardier variables: serverPort: 5000 path: / profiles: local: variables: serverAddress: localhost jobs: application: endpoints: - http://localhost:5010 load: endpoints: - http://localhost:5010 </code></pre> <h3>5.3. 启动任务</h3> <p>启动agent(打开放在一边):</p> <pre><code>crank-agent --dotnethome "/usr/share/dotnet" </code></pre> <p>启动任务(另起一个新的Shell):</p> <pre><code>git clone https://github.com/doddgu/crank.git cd crank git checkout sample crank --config ./samples/hello/hello.original.benchmarks.yml --scenario hello --load.framework net5.0 --application.framework net5.0 </code></pre> <p>然后我们等待片刻会输出以下结果</p> <p><strong>crank-agent:</strong></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2FIzJis2ZWRnGyDBSOdlZKN8Q18" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/IzJis2ZWRnGyDBSOdlZKN8Q18.svg" alt="asciicast"></a></p> <p><strong>crank:</strong></p> <p><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fasciinema.org%2Fa%2FjIiB0J3IdeMQf1vBYFz6cwUvF" target="_blank"><img style='max-width:100%' src="https://asciinema.org/a/jIiB0J3IdeMQf1vBYFz6cwUvF.svg" alt="asciicast"></a></p> <pre><code>| load | | | --------------------- | -------------- | | CPU Usage (%) | 39 | CPU使用率 | Cores usage (%) | 631 | 多核CPU使用率 | Working Set (MB) | 35 | 内存使用率 | Private Memory (MB) | 35 | 进程使用的私有内存量 | Build Time (ms) | 4,853 | 构建应用程序需要多长时间(毫秒) | Start Time (ms) | 386 | 启动应用程序需要多长时间(毫秒) | Published Size (KB) | 66,731 | 已发布应用程序的大小 (KB) | .NET Core SDK Version | 5.0.403 | .Net Core SDK 版本 | ASP.NET Core Version | 5.0.12+0bc3c37 | .Net Core版本 | .NET Runtime Version | 5.0.12+7211aa0 | .Net运行时版本 | First Request (ms) | 172 | 第一个请求耗时(这里请求是Get) | Requests | 2,086,594 | 总发送请求数 | Bad responses | 0 | 糟糕请求数(响应状态码不是2**也不是3**) | Mean latency (us) | 1,833 | 平均延迟时间 | Max latency (us) | 89,001 | 最大延迟时间 | Requests/sec | 138,067 | 每秒支持请求数 | Requests/sec (max) | 255,442 | 每秒最大支持请求数 </code></pre> <p>当你能输出以上信息的时候,证明了你已经成功跑通了整个流程</p> <p>在上面我们可以很清楚的看到场景hello下的测试结果,其中包含CPU使用率、多核CPU的使用率、内存使用率以及每秒执行的请求数等等指标</p> <p>在这一刻是不是突然觉得这个crank挺强大的,虽然还不清楚具体是咋做到的,但是真的很赞!!在这一刻是不是对它来了兴趣,想知道它到底可以做什么,为什么可以输出以上的结果?</p> <h2>6. 结尾</h2> <p>为确保后续不会因更新导致按照文档操作不可用,源码从官方源Fork了一份,其中绝大多数来自官方提供的Sample、部分文件为了更好的满足个人习惯,会在一定程度上进行调整。</p> <p>源码地址:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdoddgu%2Fcrank%2Ftree%2Fsample" target="_blank">https://github.com/doddgu/crank/tree/sample</a></p> <p>参考链接:</p> <ul> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fcrank" target="_blank">https://github.com/dotnet/crank</a></li> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Faspnet%2FBenchmarks" target="_blank">https://github.com/aspnet/Benchmarks</a></li> <li><a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D2IgfrnG-128" target="_blank">https://www.youtube.com/watch?v=2IgfrnG-128</a></li> </ul> <h2>开源地址</h2> <p>MASA.BuildingBlocks:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.BuildingBlocks" target="_blank">https://github.com/masastack/MASA.BuildingBlocks</a></p> <p>MASA.Contrib:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Contrib" target="_blank">https://github.com/masastack/MASA.Contrib</a></p> <p>MASA.Utils:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasastack%2FMASA.Utils" target="_blank">https://github.com/masastack/MASA.Utils</a></p> <p>MASA.EShop:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fmasalabs%2FMASA.EShop" target="_blank">https://github.com/masalabs/MASA.EShop</a></p> <p>MASA.Blazor:<a href="https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FBlazorComponent%2FMASA.Blazor" target="_blank">https://github.com/BlazorComponent/MASA.Blazor</a></p> <p>如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们</p> <p><img style='max-width:100%' src="https://i.loli.net/2021/11/19/NPsOdZuGfBep3DY.png" alt="16373211753064.png"></p> MASA技术团队 2023-05-27 https://www.v2tn.com/content/1685192686750818