Erlo

21-重构大杀器!流量回放让线上BUG无处遁形,QA团队集体沉默…

2025-02-04 18:30:14 发布   9 浏览  
页面报错/反馈
收藏 点赞

本文已收录在Github关注我,紧跟本系列专栏文章,咱们下篇再续!

流量:某个时间段内的所有请求,通过手段把发送到A应用的所有请求录制,然后把这些请求统一转发到B应用,让B应用接收到的请求参数跟A应用一致,实现A接收到的请求在B应用里面重新请求了一遍。整个过程即“流量回放”。

1 流量回放的意义

经常多需求并行开发,还可能夹杂着应用重构和拆分。基本很难做到不改动老逻辑,只要有改动就可能存在考虑不周。

代码小改动的业务需求,这做法一般不出问题。但对大改动应用,如应用中很多基础逻辑都被改动过,还通过已有Case去验证功能正确性,就很难保证应用上线后不出故障,毕竟我们靠自己维护的Case相对线上运行的真实环境少很多。

会向QA求助,希望他们多加Case。但因改动代码逻辑影响范围大,想圈定一个比较确定的测试范围难,相对保险的是把整个项目都回归测试,最大程度避免上线出问题,但也不是万无一失,因为线上不仅环境复杂,而且使用场景不好评估,这种方式耗时也长。

2 更可靠、廉价方案?

传统QA测试出问题的根本原因:改造后的应用在上线后出现跟应用上线前不一致的行为。

测试就是为保证改造后的应用跟改造前应用的行为一致,测试Case也都尽力模拟线上运行行为,但仅通过我们自己枚举测试Case不能代表线上所有行为。因此最好用线上流量验证,但直接把新应用上线肯定不行,一旦新改造的应用存在问题就可能导致线上调用方业务受损。

可先把线上一段时间内的请求参数和响应结果保存,然后把这些请求参数在新改造应用里重新请求,比对改造前后的响应结果是否一致,间接达到使用线上流量测试的效果。

有了线上的请求参数和响应结果后,再结合持续集成,可让改动后的代码随时用线上流量验证。

3 RPC实现流量回放

如TcpCopy、Nginx。但线上环境要使用这些工具时,还得找运维团队帮把应用安装到应用实例,再按照你的需求给配置好才能使用,整个过程繁琐而且重复做无用功,有无更好办法?尤其是在RPC情况下。

RPC是用来完成应用间通信,即应用间所有请求响应都会经RPC,那在RPC里是否就能很方便地拿到每次请求的出入参数?拿到这些出入参数后,把它们旁录下来,用异步方式发到一个固定地方保存,就完成流量回放里面的录制功能。

咋把这些请求参数转发到要回归测试的应用?

在RPC中,把能接收请求的应用叫服务提供方,只需模拟一个应用caller,把刚才收到的请求参数重发一遍到要回归测试的应用,然后比对录制拿到的请求结果和新请求的结果,完成请求回放。

RPC回放过程

相对其它现成流量回放方案,在RPC里内置流量回放功能,更方便,还可更多定制,如在线启停、方法级别录制。

4 总结

保障线上应用的稳定,不管是通过应用架构升级,还是修复现有问题。就是不仅要保障已有业务稳定,还要快速完成各种新需求,应用代码就经常变化,变化后就会引入新的不稳定因素。

为保障应用升级后,业务行为还能保持和升级前一样,大多都是依靠已有TestCase验证,但不是完全可靠。最可靠是引入线上Case去验证改造后应用,把线上真实流量在改造后应用里回放:

  • 节省整个上线时间
  • 弥补手动维护Case存在的漏测缺陷

应用引入RPC,所有请求流量都会被RPC接管,很自然在RPC里支持流量回放。虽然这个功能本身不是RPC核心功能,但对使用RPC的人,有了这功能,就可更放心升级应用。

5 FAQ

还可用流量回放做啥?

  • 监控和告警:通过持续回放关键接口的流量,实时监控系统的正确性和性能,及时发现异常。

  • 版本对比:在新旧版本同时运行时,将流量同时发送到两个版本,对比响应结果,确保新版本兼容性。

  • 自动化测试增强:结合自动化测试框架,使用真实流量作为测试用例,补充人工编写的测试用例,提高覆盖率。

  • 故障演练:模拟故障场景,观察系统在真实流量下的容错能力,比如服务降级、重试机制等。

  • 数据迁移验证:在数据迁移后,回放历史请求,验证新数据存储的正确性。

  • 用户体验分析:分析用户请求模式,优化接口性能,提升用户体验。

不过,每个用途都有其挑战。例如,版本对比需要同时维护两个版本的环境;故障演练需要精细的控制机制避免影响真实用户;数据迁移验证需要确保数据一致性和隔离性。

类似的线上验证系统

核心就是拿到线上接口的出入参和接口信息,转存到另一个系统,在这系统再调用改造、开发、或重构的接口(总之只要有变化或想测试一下同样的如入参,调用同样的方法,只是逻辑稍微不同了,是否结果一样)就可以通过,线上验证系统来验证一下。

使用限制

  • 底层数据依赖是否一致,入不一致那结果不一致也太正常了
  • 和当前系统状态或者当前系统时间是否相关,如果相关,结果也可能不一致
  • 方法是否幂等,如果不幂等,结果大概率也不一致的。

虽有局限性,不过也能解决一些问题。结果是否一致可定制化,所以对某些特殊情况也可使用。

实现思路

  • 使用动态代理,AOP切面拦截对应的方法,获取出入参
  • 把拦截信息异步转存到线上验证系统
  • 通过线上验证系统调用待验证的方法
  • 收集结果比对信息,有报警功能(当然,在验证系统侧需要先收集和配置响应的待验证系统的信息,比如:定制化结果是否一直的条件)
  • 一般就是用于线上验证或系统重构时使用

阿里开源sandbox-repeter:https://github.com/alibaba/jvm-sandbox-repeater。

Q:既然能在rpc做,是不是可放到网关做,如机房迁移或服务重新部署一套,在网关做流量采集然后回访到另一网关,后面的服务都涉及到了,可行?

A:在入口流量上做也是一种方案。

Q:应该还可恢复数据,如一段时间数据由于某种原因丢,用流量回放功能恢复这段时间数据,当然要求接口幂等,否则会导致错误数据。

A:恢复数据更多是采用log。

Q:游戏角度,可用流量回放进行玩家脚本录制,然后多线程进行大批量脚本执行从而达到压力测试的效果。

一般rpc都会有扩展,只要在扩展里面进行异步处理一下就可以满足。

Q:只是录制请求和响应感觉不够。 响应可能和用户数据有关。 响应=请求参数+用户状态+其他依赖方状态。

A:你想表达数据隔离?好比如count场景确实可能不够。

Q:流量回放还可:

  • QA做接口探活,用线上数据调用接口(http接口只探get方法)
  • 算法逻辑的验证:可用历史请求参数重跑一遍新算法逻辑,验证新算法逻辑的效果

Q:参数和返回值也得存下来,安全隐患较大

A:确实,存储请求和响应数据可能包含敏感信息,比如用户个人信息、支付信息等。因此,在实施流量回放时,必须对数据进行脱敏处理,或者确保存储和传输的安全性。例如,可以对敏感字段进行加密或替换,避免数据泄露。

Q:非幂等接口想用的话,TC里最好有完整的创建数据,清理数据调用,难度也比较大。

A:如支付接口,如果回放时重复调用,可能导致多次扣款。这时候,处理起来确实复杂。可能方案:

  • 在测试环境中使用mock的支付服务,避免真实交易
  • 在回放前清理测试数据,确保每次回放都在干净的环境中进行
  • 标记测试请求,让下游系统识别并处理测试数据,避免影响真实业务

Q:感觉没啥用处。如付款接口,你不能通过入参、出参相同就判断里面执行结果相同,都是返回付款成功,你咋知道实际付款了一次or两次?你可能会说把付款成功金额返回,但有bug的情况,付款了两次,却返回一次的成功金额。按回放功能来跑,这bug发现不了。

A:如果系统存在bug,导致重复付款但返回成功一次,这种情况流量回放可能无法发现,因为响应结果相同。这时需结合日志分析或其他监控手段检测重复操作。或在回放时不仅比对响应结果,还检查数据库状态或其他副作用,但这增加复杂度。

重现生产问题:不好定位问题的时候,也是可以试试流量回放重现生产问题。

Q:用生产环境的流量来做压测。

A:使用真实流量进行压测,比人工构造的请求更贴近实际场景,能更真实地反映系统性能。但需要注意,压测环境和生产环境的数据隔离,避免影响真实用户。

Q:可是场景模拟,镜像流量只是其中一步,所有外部接口的mock也得和线上当时的场景一致,不然最后也可能脱离预期。

A:外部接口的mock。为了准确模拟线上环境,所有依赖的外部服务在回放时需要保持与录制时一致的状态,或者使用录制的外部响应数据进行mock。否则,回放结果可能因为外部服务状态变化而不准确。

Q:流量回放适用的方法是不是有限制,需要幂等的方法才可以?

A:只要做好隔离了,不用区分。

本文由博客一文多发平台 OpenWrite 发布!

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认