引言
随着功能的迭代和业务的增长,一套开发环境和一套测试环境往往很难满足需求。不同的功能、不同的分支代码在同一套环境测试,难免互相影响。所以看到公司往往有多套开发环境和多套测试环境,以应对这些冲突。多套环境带来的运维成本增加,例如:像中间件、DB、机器等往往需要独立部署。另外多套环境也难以解决众多开发测试需求,还可能造成冲突。
本文介绍通过测试场的方式来解决众多环境的的问题,主要内容有:
- 单套环境对开发测试的影响
- 测试场启动流程
- 测试场调用流程
- 中间件在测试场中的实现
一、单环境对开发测试的影响
下面整理了同一套环境开发测试中的常见问题,RPC调用错乱、消息消费错乱以及数据问题。
1.服务RPC调用错乱
如图所示,调用链路调用关系,A调用B,B调用C,接着C调用D,最后D调用E。
在同一套环境中,A和B两个服务分别拉了两个分支开发不同的功能。
- A-branch1与B-branch1
- A-branch2与B-branch2
期望A-branch1调用B-branch1,而A-branch2调用B-branch2。但有可能A-branch1调用B-branch2,A-branch2调用了B-branch1。也就是A和B之间的调用随机的,给开发调试造成困扰。
2.发送消费消息错乱
如图所示,调用链路调用关系,A调用B,B发送消息到消息集群,C消费后RPC调用D,最后D调用E。
在同一套环境中,B和C两个服务分别拉了两个分支开发不同的功能。
- B-branch1与C-branch1
- B-branch2与C-branch2
期望B-branch1发送的消息被C-branch1消费,而B-branch2发送的消息被C-branch2消费。但有可能B-branch1发送的消息被C-branch2消费了,B-branch2发送的消息被C-branch1消费了。也就是C-branch1和C-branch2消费时随机的,给开发调试造成困扰。
3.存储数据被改错乱
数据被改这个容易理解,大家共用一套数据库,各管各的开发调试。
- 把公共数据改了
- 把别人的数据改了
由于数据修改,影响了其他人的调试,给别人造成困扰。
二、测试场启动流程
1.测试场启动流程图示
2.测试场启动流程概述
- 在发布系统【创建测试场】该测试场中可以拉入联调的上下游服务以及分支
- 在发布系统脚本中通过-D将测试场参数(例如:-DtestGround=abcd)传入,RPC框架该标记写入注册中心,完成【节点打标】。例如:在注册中心节点1.2.3.4写入tag=abcd
- 消息集群通过不同主题来完成【消息流量隔离】,在启动节点可以动态拼接不同的消费组来订阅不同的主题。例如:abcd_melon_consumer 订阅 abcd_melon_topic 完成测试场abcd的流量隔离
三、测试场调用流程
1.RPC调用流程
- 测试场中提供一套稳定环境,该环境部署了master分支代码
- 在测试场1中,有联调服务A-branch1和B-branch1,没有其他服务。B-branch1调用C转回稳定环境调用
- 在测试场2中,有联调服务A-branch2和B-branch2,没有其他服务。B-branch2调用C转回稳定环境调用
2.消息调用流程
- 测试场中提供一套稳定环境,该环境部署了master分支代码
- 服务B发送消息到melon_topic,被服务C的消费组melon_consumer订阅,以及被另一个服务APP-X的消费组melon_appx_consumer订阅
- 在测试场1中,有联调服务B-branch1和C-branch1,没有其他服务,B-branch1发的消息被C-branch1消费
- 在测试场1中,通过不同主题abcd1_melon_topic和不同消费组abcd1_melon_consumer实现发送和消费流量隔离
- 在测试场2中,有联调服务B-branch2和C-branch2,没有其他服务,B-branch2发的消息被C-branch2消费
- 在测试场2中,通过不同主题abcd2_melon_topic和不同消费组abcd2_melon_consumer实现发送和消费流量隔离
- 在稳定环境中,APP-X的消费组melon_appx_consumer没有在测试场联调,需消费melon_topic、abcd1_melon_topic以及abcd2_melon_topic三个主题的消息
- 在稳定环境中,当测试场中部署了C-branch1和C-branch2时,稳定环境服务C的消费组melon_consumer,只消费melon_topic的消息
- 在稳定环境中,当测试场中只部署了C-branch1,而没有C-branch2时,稳定环境服务C的消费组melon_consumer,需消费melon_topic、abcd2_melon_topic两个主题的消息
- 在稳定环境中,当测试场中只部署了C-branch2,而没有C-branch1时,稳定环境服务C的消费组melon_consumer,需消费melon_topic、abcd1_melon_topic两个的消息
- 在稳定环境中,当测试场中没有部署了C-branch1和C-branch2时,稳定环境服务C的消费组melon_consumer,需消费melon_topic、abcd1_melon_topic、abcd2_melon_topic三个主题的消息
四、中间件在测试场中的实现
测试场多环境逻辑隔离主要依赖基础组件提供的能力支持,主要涉及标记链路透传、RPC框架节点打标和选择、消息的流量隔离以及网关和分布式调度的标记透传。
1.链路标记透传
链路透传在众多方案中都是必备的,比如:全链路压测、链路tracing,可参考下面两种实现方式:
- OpenTracing Baggage
- transmittable-thread-local
备注:通过中间件提供公共组件完成链路标记向下透传。
2.RPC框架节点打标和选择
测试场中需要对节点打标,再根据上下文透传的标记选出打标节点发起调用,具体RPC框架能力为:
- 节点打标,比如:对1.2.3.4节点打上测试场的标【abcd】
- 节点选择,比如:根据链路透传过来的标记【abcd】选择对应的打标节点
- 默认节点,如果没有打标节点,需要选择默认节点
- 链路透传,选择了节点发起RPC调用,继续透传测试场标记【abcd】
3.消息的流量隔离
对于消息来说,需要对不同的测试场流量进行隔离,如上第三部分测试场调用流程中的消息调用,场景也比较多,消息的方案复杂的多。
- 流量隔离,通过不同的主题和消费组完成测试场流量的隔离
- 消息发送侧,如果链路中有测试场标记,则动态拼接隔离主题,将该流量发送到隔离主题,例如:abcd_melon_topic。同时在元数据中心记录【发送侧测试场标记】
- 消息消费侧,如果该消费组被拉入测试场,通过隔离消费组订阅隔离主题,实现消费流量隔离,例如:abcd_melon_consumer订阅abcd_melon_topic。同时在元数据中心记录【消费侧测试场标记】
- 稳定环境的消费组,需要监听【发送侧测试场标记】和【消费侧测试场标记】的变化,实现动态接管测试场的流量或者剔除测试场流量,例如:稳定环境消费组melon_consumer除了订阅melon_topic外,是否订阅abcd_melon_topic;取决于测试场中是否有abcd_melon_consumer
- 在实践中可以在RocketMQ/Kafka集群开启自动创建主题和消费组权限,并在新的集群自动创建的主题和消费组与原集群分离,方便清理。
4.其他组件
测试场的流量隔离主要在RPC框架和消息队列实现,网关和分布式调度等主要参与标记透传。另外,数据可以通过构造偏移数据来规避数据的不一致,降低数据库实现逻辑隔离的复杂性。