从程序员到架构师开发运维场景实战篇:一人一套测试环境

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
云原生网关 MSE Higress,422元/月
简介: 一人一套测试环境本篇开始讲第16次架构经历:一人一套测试环境。同样,先介绍业务场景。业务场景:测试环境何时能释放出来使用当时,公司的基础设施使用的是虚拟机,而且还未迁移到容器。

一人一套测试环境

本篇开始讲第16次架构经历:一人一套测试环境。同样,先介绍业务场景。

业务场景:测试环境何时能释放出来使用

当时,公司的基础设施使用的是虚拟机,而且还未迁移到容器。

公司一共搭建了3套测试环境。之所以是3套而不是只有1套,主要是考虑到多个项目同时进行时需要分开测试和分开上线,而3套测试环境在一定程度上可以避免这些并行项目因为排队而导致延期的情况。

一般来说,研发流程是这样的:需求宣讲——>接口/方案设计——>功能开发——>联调——>测试——>预生产——>上线。

在这3套测试环境中,一套专门用于联调,另外两套专门用于测试。

那么,一套联调测试环境够用吗?答案是不太够,因为经常需要排期使用。那么两套测试环境够用吗?也不够。这里讲一个具体的例子。

之前有一个项目已经进入测试环节,功能测试反馈没问题后等待第三方验收,可是第三方的验收拖了很久,以至于不得不继续占用测试环境。

之后又有一个小的迭代项目要求一周后上线,并且还有一个上百人做的超大项目刚进入测试阶段,所以又需要两套测试环境。此时测试环境就不够用了,而且联调环境都被征用了。

然后,业务方还提了一个加急需求要求当周上线,于是出现了下面这段对话。

甲:“我们有个紧急需求这周四要求上线,你们能不能把测试1让一

下?”

乙:“不行,我们这个功能需要测试一周,下周四就要上线了。如果让

给你们一天,我们就要延期一天上线了。”

甲:“其实是两天……”乙:“那更不行了。要不你问问XX,他们在做的项目周期长,应该能让

给你们两天。”

甲:“不行吧,那个项目号称公司第一优先级,我开不了口啊!”

乙:“不然你们就用测试3?”

甲:“我哪敢啊,那个验收项目是领导亲自跟的。”

乙:“可是我们也不能延期啊,业务方都确认过很多次了,我们也跟合

作伙伴谈好了。”

“……”

最终就是因为抢测试环境的问题,导致紧急需求上不了线,有苦也没地方说。

在实际工作中,一个组同时开展好几个项目的情况经常发生,尤其是业务对接方比较多的小组。为此,公司决定着手解决这个问题。

解决思路

公司希望达成的目标是可以快速搭建一套新的测试环境,用完马上销毁。针对这个目标,解决思路如下。

1)利用容器的特性,在几秒内快速启动服务实例。

2)将测试环境需要搭建的服务通过容器实例部署起来。

3)将这些容器通过Kubernetes管理(编排)起来。

那么,这一整套测试环境都需要包含哪些服务器?

如图17-1所示,每套测试环境中需要部署的组件有MQ、ZooKeeper、Redis、配置中心、数据库、API服务、后台服务、网关等。

• 图17-1 测试环境服务范围

决定使用容器灵活创建测试环境后,项目组针对每一套容器环境是包含全部组件还是部分特定组件调研了很久。

用过容器的开发人员都知道,在容器中部署MQ、ZooKeeper、Redis或配置中心是一件很简单的事情。比如使用容器部署Redis,只需要输入以下两行命令即可。

使用容器部署ZooKeeper、MQ的方法与之类似。不过这里有点不一样的是,公司所有的中间件基本都不是纯净的开源版本。比如配置中心,公司并没有使用Spring Cloud Config,也没有使用Nacos,而是使用了一个完全自研的产品(MQ和网关都是自研的),它既不支持容器,也不支持单机版。而ZooKeeper、Redis是基于开源版本的,并在服务端加了一些封装。

此时,客户端强制使用一个自定义的客户端SDK,且使用的中间件必须强绑定配置中心。

之前评估过,如果把这些中间件部署到容器中,将会出现以下3种情况。

1)中间件服务端改造成本大。

2)客户端的SDK需要进行大量的改造。

3)最重要的一点是,会导致容器环境与其他普通环境存在很大的代码差异。因此,即使在容器中测试没问题,也需要在其他环境中进行大量测试,此时容器测试环境就没有什么意义了。为此,最终决定在容器测试环境中只部署独立的API服务或后端服务,其他组件直接重用测试环境的中间件,如图17-2所示。

• 图17-2 容器测试环境示意图

基于以上设计方案,如果想快速部署一套独立的测试环境,一般需要解决哪些问题?因为容器测试环境复用了测试环境的一些组件,所以需要解决以下5个问题。

API服务间的隔离

如何确保容器环境的客户端请求能到达容器的API服务,而非仍然到达测试环境的API服务?

当 时 的 系 统 是 这 么 设 计 的 : 每 一 个 API 服 务 中 都 会 带 一 个 配 置 项channelID,然后客户端每次访问API时都需要加上一个channelID参数;网关层接收到这个请求后,会根据channelID将请求匹配到对应channelID的API服务中(当然URL也需要匹配),此时整个隔离过程就比较简单了。

先介绍一下具体的研发流程:每个项目都有一个JIRA Issue,而XXX123就是一个JIRA Issue ID,项目组会为每个项目单独创建一套容器测试环境,于是这个Issue ID自然而然地被当作了环境标识。

再回到API的隔离。一般来说,客户端会把上面的channelID放在配置文件中,等到容器测试时再打一个包,此包中channelID的配置值为JIRA IssueID,也就是容器测试环境的标识。最后,会在容器环境打包API服务时,自动将channelID的配置值改为JIRA Issue ID。

具体的调用请求处理过程如图17-3所示。

• 图17-3 利用channelID导向不同容器环境

在图17-3中,网关层接收到所有请求后,会根据不同的channelID将请求分发到不同的API服务中。这样,API服务的隔离问题就解决了。

后台服务间的隔离

如何确保容器环境部署的服务只调用容器服务,而测试环境虚拟机的服务只调用虚拟机服务?

当时的系统是这样设计的:在打包RPC服务时,将一个环境变量env的值设置为容器测试环境的标识,也就是JIRA Issue ID,比如XXX123;然后每个RPC服务注册ZooKeeper时,将在Service的metadata中加一个tag参数,并设置tag的值为XXX123。之后,RPC服务只会调用同样tag的服务。这是什么意思?

比如测试环境中有3个UserService,其中,一个是测试环境的虚拟机,两个 是 容 器 测 试 环 境 部 署 的 UserService 。 前 者 的 tag 为 空 , 后 两 个 容 器UserService 注 册 ZooKeeper 后 , 它 们 的 tag 值 分 别 为 XXX123 和 XXX245 。

OrderService调用UserService时,如果OrderService也是XXX123这个容器环境的服务,则它只会调用带XXX123这个tag值的UserService;如果它是正常虚拟机的服务,则只会调用不带tag值的UserService。

这样,后台RPC服务间的隔离问题就解决了。

以上要点中并没有提及ZooKeeper,因为API和RPC服务的隔离问题解决后,ZooKeeper的数据隔离问题基本也解决了。其实,ZooKeeper在每套测试环境中起到的作用只是API服务和RPC服务的注册发现。

MQ和Redis隔离

如何确保容器环境和虚拟机之间的MQ消息不互串、Redis数据不互相影响?

项目组本来想使用类似tag的概念来解决这个问题,通过封装MQ与Redis的客户端代码让它们只消费同样env值的服务生产的内容。

但是,还需要遵循以下原则:尽量减少容器测试环境与正式环境的代码差异。针对这个问题,项目组讨论了很久,最终认为没必要专门定制,只需保证走测试流程时使用不同的测试数据就可以了(不同的项目一般都会使用不同的测试数据,包括不同的用户、不同的订单等),这样基本不会再出现不同容器测试环境流转相同MQ消息、缓存数据的情况了。

当然,Redis中的一些通用数据还是会被共同使用,比如城市的基础数据。不过这些数据即使在不同容器测试环境之间互相串联也没关系。

配置中心数据的隔离

对于配置中心是这样设计的:如果容器测试环境的值与虚拟机测试环境的值不一样,不会修改配置中心的值,而是在容器环境的启动脚本中动态加上针对各自容器测试环境的环境变量,然后在业务代码中启动环境变量优先级高于配置中心的参数,这样就确保了容器测试环境的特殊配置,从而不影响配置中心的值。

数据库间的数据隔离

数据库互相影响的情况一般有两种。

1.测试数据互相影响

这一点其实和MQ、Redis的情况一样,只需要保证测试数据各自独立即可。

2.数据库结构兼容问题

比如同时进行两个项目,XXX123这个项目删除了user这张表的updateFlag字段,而XXX100这个项目还需要使用这个字段,此时如果两个项目共用一个数据库就会互相影响。

其实,这一点在第2章中介绍过:每次版本迭代时,都需要保证数据库可以兼容前一个版本的代码。比如刚刚那个例子,不能直接在XXX123中删掉updateFlag字段,而是等XXX100上线后再删掉。

关于数据库兼容前一个版本,再举一个例子。比如在XXX123这个项目中增加了一个字段updateUserID,且该字段的值为必填,否则数据就会报错;而XXX100这个项目并不会更新updateUserID,这样如果XXX123读到了XXX100写入的数据就会报错。

这种情况该如何处理?此时可以在项目XXX123中增加一些代码让它可以容错,即允许updateUserID为空。也可以将项目XXX123与项目XXX100部署到不同测试环境的数据库中。

解决完上面这些问题后,基于现有测试环境快速部署多套容器环境的方案设计就基本完成了,接下来再简单介绍一下使用流程。

使用流程

使用流程是这样的,每次新建一个工程时(新的API或者后台服务)都会在Jenkins上配置一个Job,而这个Job需要接受以下3个参数。1)Branch,即需要部署的代码分支。

2)测试环境test1/test2/test3(已经有3个测试环境,它决定了部署需要使用哪个测试环境的中间件)。

3)容器测试环境标识,也就是JIRA Issue ID。

这 个 Job 启 动 时 , 需 要 调 用 一 个 小 工 具 , 而 这 个 小 工 具 需 要 连 接Kubernetes创建namespace(=JIRA Issue ID),然后在namespace中增加一个pod(pod中运行的是专门为JIRA Issue ID打包的代码)。

在 做 某 个 项 目 时 , 假 设 XXX123 需 要 使 用 UserAPI 、 UserService 、OrderService 、 ProductService , 就 会 配 置 一 个 新 的 Jenkins Job 来 联 动UserAPI、UserService、OrderService、ProductService的Job,并且将各个服务对应的Branch、测试环境和JIRA Issue ID传入Jenkins Job(这些值都通过硬编码配置在新的Jenkins Job中)。之后,每次点击这个项目的JenkinsJob时,就可以对其容器测试环境进行部署了。

当然,如果项目成员想自己部署一套环境,此时只需单独配置一个新的Jenkins Job,并找一个不一样的(比如开发任务的Issue ID)容器测试环境标识即可。

通过这套方案可以实现图17-4所示的效果,项目基本不会再陷入因缺少测试环境而延期的境地。

• 图17-4 每个需求独立的测试进程

一人一套测试环境的方案成本其实非常小,因为代码改动很少,且一两周就可以把整个方案实施完成(时间主要用在申请服务器和部署Kubernetes上)。

此方案上线后,得到了使用者的一致好评,尤其是测试人员,这里总结了3点原因。

1)再也不需要因为协调测试环境花很多时间沟通了。

2)一键就可以将相关服务部署起来,不再需要一个服务一个服务地部署。

3)因为容器测试环境的搭建很简单,开发人员每完成一个功能,测试人员即可介入测试,而不需要等整个项目提测后再介入,大大缩短了提测后的测试周期。

总体来说,这个项目的效果非常好,而且之后的容器测试环境基本上保持人均一套的使用状态。

小结

到这里,16次架构经历也就讲完了。接下来的结束语,不讲架构经历,将通过3次真实的经历向大家分享:如何成为不可或缺的人。

本文给大家讲解的内容是开发运维场景实战:一人一套测试环境

  1. 下篇文章给大家讲解的内容是开发运维场景实战:如何成为不可或缺的人?
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!!
  4. 本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。
相关文章
|
4天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
23 3
|
18天前
|
运维 监控 Java
后端开发中的微服务架构实践与挑战####
在数字化转型加速的今天,微服务架构凭借其高度的灵活性、可扩展性和可维护性,成为众多企业后端系统构建的首选方案。本文深入探讨了微服务架构的核心概念、实施步骤、关键技术考量以及面临的主要挑战,旨在为开发者提供一份实用的实践指南。通过案例分析,揭示微服务在实际项目中的应用效果,并针对常见问题提出解决策略,帮助读者更好地理解和应对微服务架构带来的复杂性与机遇。 ####
|
21天前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
39 8
|
17天前
|
消息中间件 运维 安全
后端开发中的微服务架构实践与挑战####
在数字化转型的浪潮中,微服务架构凭借其高度的灵活性和可扩展性,成为众多企业重构后端系统的首选方案。本文将深入探讨微服务的核心概念、设计原则、关键技术选型及在实际项目实施过程中面临的挑战与解决方案,旨在为开发者提供一套实用的微服务架构落地指南。我们将从理论框架出发,逐步深入至技术细节,最终通过案例分析,揭示如何在复杂业务场景下有效应用微服务,提升系统的整体性能与稳定性。 ####
31 1
|
22天前
|
监控 Serverless 云计算
探索Serverless架构:开发实践与优化策略
本文深入探讨了Serverless架构的核心概念、开发实践及优化策略。Serverless让开发者无需管理服务器即可运行代码,具有成本效益、高可扩展性和提升开发效率等优势。文章还详细介绍了函数设计、安全性、监控及性能和成本优化的最佳实践。
|
18天前
|
消息中间件 运维 API
后端开发中的微服务架构实践####
本文深入探讨了微服务架构在后端开发中的应用,从其定义、优势到实际案例分析,全面解析了如何有效实施微服务以提升系统的可维护性、扩展性和灵活性。不同于传统摘要的概述性质,本摘要旨在激发读者对微服务架构深度探索的兴趣,通过提出问题而非直接给出答案的方式,引导读者深入
37 1
|
19天前
|
负载均衡 监控 API
后端开发中的微服务架构实践与挑战
本文深入探讨了微服务架构在后端开发中的应用,分析了其优势和面临的挑战,并通过案例分析提出了相应的解决策略。微服务架构以其高度的可扩展性和灵活性,成为现代软件开发的重要趋势。然而,它同时也带来了服务间通信、数据一致性等问题。通过实际案例的剖析,本文旨在为开发者提供有效的微服务实施指导,以优化系统性能和用户体验。
|
22天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
51 1
|
2天前
|
前端开发 搜索推荐 安全
陪玩系统架构设计陪玩系统前后端开发,陪玩前端设计是如何让人眼前一亮的?
陪玩系统的架构设计、前后端开发及前端设计是构建吸引用户、功能完善的平台关键。架构需考虑用户需求、技术选型、安全性等,确保稳定性和扩展性。前端可选用React、Vue或Uniapp,后端用Spring Boot或Django,数据库结合MySQL和MongoDB。功能涵盖用户管理、陪玩者管理、订单处理、智能匹配与通讯。安全性方面采用SSL加密和定期漏洞扫描。前端设计注重美观、易用及个性化推荐,提升用户体验和平台粘性。
12 0
|
23天前
|
消息中间件 监控 API
后端开发中的微服务架构实践与挑战####
本文深入探讨了微服务架构在现代后端开发中的应用,分析了其优势、实施过程中的关键考虑因素及面临的挑战。不同于传统的单体应用,微服务通过拆分功能模块为独立服务,提升了系统的灵活性和可维护性。我们将从微服务的基本概念入手,逐步剖析其在真实场景下的应用案例,并讨论如何有效应对服务间通信、数据一致性等复杂问题,旨在为开发者提供一套实用的微服务落地指南。 ####
19 0
下一篇
DataWorks