极客时间已完结课程限时免费阅读

21 | 流量回放:保障业务技术升级的神器

21 | 流量回放:保障业务技术升级的神器-极客时间

21 | 流量回放:保障业务技术升级的神器

讲述:张浩

时长07:54大小7.23M

你好,我是何小锋。上一讲我们学习了时钟轮在 RPC 中的应用,核心原理就一个关键字“分而治之”,我们可以把它用在任何需要高效处理大量定时任务的场景中,最具有代表性的就是在高并发场景下的请求超时检测。
回顾完上一讲的重点,我们就进入咱们今天的主题,一起看看流量回放在 RPC 里面的应用。
如果你经常翻阅一些技术文章的话,可能你会不止一次看到过“流量回放”这个词。我简单地介绍一下,所谓的流量就是某个时间段内的所有请求,我们通过某种手段把发送到 A 应用的所有请求录制下来,然后把这些请求统一转发到 B 应用,让 B 应用接收到的请求参数跟 A 应用保持一致,从而实现 A 接收到的请求在 B 应用里面重新请求了一遍。整个过程我们称之为“流量回放”。
这就好比今晚有场球赛,但我没空看,但我可以利用视频录播技术把球赛录下来,我随时想看都可以拿出来看,画面是一模一样的。
那在系统开发的过程中,回放功能可以用来做什么呢?

流量回放可以做什么?

我个人感觉,在我们日常开发过程中,可以专心致志地写代码、完成业务功能,是件很幸福的事儿,让我比较头疼的是代码开发完成后的测试环节。
在团队中,我们经常是多个需求并行开发的,在开发新需求的过程中,我们还可能夹杂着应用的重构和拆分。每到这个时候,我们基本很难做到不改动老逻辑,那只要有改动就有可能会存在考虑不周全的情况。如果你比较严谨的话,那可能在开发完成后,你会把项目里面的 TestCase 都跑一遍,并同时补充新功能的 TestCase,只有所有的 TestCase 都跑通后才能安心。
在代码里面,算小改动的业务需求,这种做法一般不会出问题。但对于大改动的应用,比如应用中很多基础逻辑都被改动过,这时候如果你还是通过已有的 Case 去验证功能的正确性,就很难保证应用上线后不出故障了,毕竟我们靠自己维护的 Case 相对线上运行的真实环境来说还是少了很多。
这时候我们会向更专业的 QA 测试人员求助,希望他们能从 QA 角度多加入一些 Case。但因为我们改动代码逻辑影响范围比较大,想要圈定一个比较确定的测试范围又很难,坦白讲这时候相对保险的方式就是 QA 把整个项目都回归测试一遍。这种方式已经是在最大程度上避免上线出问题了,但从概率角度上来讲也不是万无一失的,因为线上不仅环境复杂,而且使用场景也并不好评估,还有就是这种方式耗时也很长。
这就是我认为最让人头疼的原因,靠传统 QA 测试的方式,不仅过程费时,结果也不是完全可靠。那有没有更可靠、更廉价的方案呢?
传统 QA 测试出问题的根本原因就是,因为改造后的应用在上线后出现跟应用上线前不一致的行为。而我们测试的目的就是为了保证改造后的应用跟改造前应用的行为一致,我们测试 Case 也都是在尽力模拟应用在线上的运行行为,但仅通过我们自己的枚举方式维护的 Case 并不能代表线上应用的所有行为。因此最好的方式就是用线上流量来验证,但是直接把新应用上线肯定是不行的,因为一旦新改造的应用存在问题就可能会导致线上调用方业务受损。
我们可以换一种思路,我可以先把线上一段时间内的请求参数和响应结果保存下来,然后把这些请求参数在新改造的应用里重新请求一遍,最后比对一下改造前后的响应结果是否一致,这就间接达到了使用线上流量测试的效果。有了线上的请求参数和响应结果后,我们再结合持续集成过程,就可以让我们改动后的代码随时用线上流量进行验证,这就跟我录制球赛视频一样,只要我想看,我随时都可以拿出来重新看一遍。

RPC 怎么支持流量回放?

那在实际工作中,我们该怎么实现流量回放呢?
我们常见的方案有很多,比如像 TcpCopy、Nginx 等。但在线上环境要使用这些工具的时候,我们还得需要找运维团队帮我们把应用安装到应用实例里面,然后再按照你的需求给配置好才能使用,整个过程繁琐而且总数重复做无用功,那有没有更好的办法呢?尤其是在应用使用了 RPC 的情况下。
在前面我们不止一次说过,RPC 是用来完成应用之间通信的,换句话就是说应用之间的所有请求响应都会经过 RPC。
既然所有的请求都会经过 RPC,那么我们在 RPC 里面是不是就可以很方便地拿到每次请求的出入参数?拿到这些出入参数后,我们只要把这些出入参数旁录下来,并把这些旁录结果用异步的方式发送到一个固定的地方保存起来,这样就完成了流量回放里面的录制功能。
有了真实的请求入参之后,剩下的就是怎么把这些请求参数转发到我们要回归测试的应用里面。在 RPC 中,我们把能够接收请求的应用叫做服务提供方,那就是说我们只需要模拟一个应用调用方,把刚才收到的请求参数重新发送一遍到要回归测试的应用里面,然后比对录制拿到的请求结果和新请求的结果,就可以完成请求回放的效果。整个过程如下图所示:
RPC回放过程
相对其它现成的流量回放方案,我们在 RPC 里面内置流量回放功能,使用起来会更加方便,并且我们还可以做更多定制,比如在线启停、方法级别录制等个性化需求。

总结

保障线上应用的稳定,是我们研发同学每天都在努力耕耘的一件事,不管是通过应用架构升级,还是修复现有问题的方式。实际情况就是我们不仅要保障已有业务的稳定,还需要快速去完成各种新业务的需求,这期间我们的应用代码就会经常发生变化,而发生变化后就可能会引入新的不稳定因素,而且这个过程会一直持续不断发生。
为了保障应用升级后,我们的业务行为还能保持和升级前一样,我们在大多数情况下都是依靠已有的 TestCase 去验证,但这种方式在一定程度上并不是完全可靠的。最可靠的方式就是引入线上 Case 去验证改造后的应用,把线上的真实流量在改造后的应用里面进行回放,这样不仅节省整个上线时间,还能弥补手动维护 Case 存在的缺陷。
应用引入了 RPC 后,所有的请求流量都会被 RPC 接管,所以我们可以很自然地在 RPC 里面支持流量回放功能。虽然这个功能本身并不是 RPC 的核心功能,但对于使用 RPC 的人来说,他们有了这个功能之后,就可以更放心地升级自己的应用了。

课后思考

除了上面我提到的可以使用流量回放功能来验证改造后的应用逻辑,我们还可以用流量回放来做哪些有意义的事儿?
欢迎留言和我分享你的思考,也欢迎你把文章分享给你的朋友,邀请他加入学习。我们下节课再见!
分享给需要的人,Ta购买本课程,你将得18
生成海报并分享

赞 13

提建议

上一篇
20 | 详解时钟轮在RPC中的应用
下一篇
22 | 动态分组:超高效实现秒级扩缩容
unpreview
 写留言

精选留言(29)

  • 2020-05-17
    流量回放——之前组内做过一个类似的系统,我们叫线上验证系统——其核心就是拿到线上接口的出入参和接口信息,然后转存到另一个系统,在这个系统再调用改造、开发、或重构的接口(总之只要有变化或者想测试一下同样的如入参,调用同样的方法,只是逻辑稍微不同了,是否结果一样)就可以通过,线上验证系统来验证一下。 使用上当然,有限制啦! 首先,底层数据依赖是否一直,入不一致那结果不一致太正常了。 其次,和当前系统状态或者当前系统时间是否相关,如果相关,结果也可能不一致。 再次,就是方法是否幂等,如果不幂等,结果大概率也不一致的。 虽然,有局限性,不过也能解决一些问题,另外,结果是否一致是可定制化的,所以,对于某些特殊情况也是可以使用的。 实现思路 1:使用动态代理,切面拦截对应的方法,获取出入参 2:把拦截信息异步转存到线上验证系统 3:通过线上验证系统调用待验证的方法 4:收集结果比对信息,有报警功能(当然,在验证系统侧需要先收集和配置响应的待验证系统的信息,比如:定制化结果是否一直的条件) 5:我们一般就是用于线上验证或系统重构时使用
    展开
    共 2 条评论
    20
  • 冬风向左吹
    2020-04-20
    阿里最近开源的sandbox-repeter
    共 3 条评论
    17
  • Darren
    2020-04-08
    老师,请教个问题,那既然能放在rpc做,那是不是也可以放到网关去做,比如我们机房迁移,或者服务重新部署一套的话,在网关做流量采集然后回访到另外一个网关,后面的服务都涉及到了,这样是否可行?

    作者回复: 在入口流量上做也是一种方案

    共 3 条评论
    7
  • ant
    2020-05-18
    从游戏的角度来看,我们可以利用流量回放进行玩家脚本录制,然后多线程进行大批量脚本执行从而达到压力测试的效果。
    6
  • 雨霖铃声声慢
    2020-04-08
    流量回放功能应该还可以用来恢复数据,比如一段时间的数据由于某种原因丢失了,那我们就应该用流量回放功能恢复这段时间的数据,当然要求接口是幂等的,否则会导致错误数据。

    作者回复: 恢复数据更多会采用log

    6
  • 高源
    2020-04-08
    还得实践啊😊这个比较高级,能有例子参考学习最好了😊

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

    共 2 条评论
    2
  • 每天晒白牙
    2020-04-08
    一直都是用 tcpcopy

    作者回复: rpc上支持更方便

    2
  • Sic Pavis
    2021-06-22
    只记录入参出参,是远远达不到回放的效果的,实际情况远比文中介绍的复杂。 因为实际业务处理,经常涉及非常多的外部依赖:数据库、缓存、外部服务响应。 在回放的服务上,没有办法把这些依赖和线上环境完全保持一致。 因此,不仅要记录出参入参,至少还需要记录所有外部调用的依赖的响应内容。在回放时,mock 掉这些调用
    展开
    共 1 条评论
    1
  • chai
    2021-04-25
    全链路压测、子链路压测
    1
  • 脏嘻嘻
    2021-02-08
    以前使用 GoReplay 去记录和重放 Http 流量,用于日常测试和压测
    2
  • 司空摘星
    2020-12-04
    流量回放,是为了模拟线上环境吧。有系统性的模拟线上环境的方法,或者有什么成熟的解决方案吗?
    1
  • Json Dumps
    2020-04-17
    只是录制请求和响应感觉不够。 响应可能和用户数据有关。 响应=请求参数+用户状态+其他依赖方状态。

    作者回复: 你可能想表达的是数据隔离吧?好比如count场景确实可能不够

    1
  • Jackey
    2020-04-14
    用生产环境的流量来做压测?

    作者回复: 不错的场景

    2
  • Reason
    2020-04-08
    流量回放适用的方法是不是又限制,需要幂等的方法才可以?

    作者回复: 只要做好隔离了,不用区分

    1
  • hello
    2020-04-08
    老师,rpc的流量复制及回放能否举个代码示例,伪代码级别就好,多谢!
    1
  • Dovelol
    2020-04-08
    还可以压测,性能优化之类的

    作者回复: 是的

    1
  • 小乙哥
    2022-06-28
    流量回放的请求接口如果有DB操作(比如,创建订单),线上接口是创建成功,回放的时候已经有订单(创建失败)。这种情况回放流量怎么解决呢?
    共 3 条评论
  • 清风@知酒烈
    2022-05-30
    老师请问一个问题,我们的项目中也是使用dubbo,但是发现所有的pojo都必须实现java的Serializable接口,不然就会报错。如果说dubbo的序列化默认使用的是Hessian2,那为什么实体类还是要实现Serializable呢?
    共 1 条评论
  • 核桃
    2022-02-13
    流量回放,其实本质上就是在大量重构之后,希望模拟线上真实的压力情况来暴露问题。而一种实现思路,可以考虑流量镜像,就是一个旧的还在运行的集群A,然后一个B改造后的集群,然后把请求流量复制也打一份到B上面看看,成本和维护代价还是挺高的。
  • 轨迹
    2021-01-11
    流量录制之后,成倍的重放,达到压测的效果