编者按:本文源自阿里云云效团队出品的《阿里巴巴DevOps实践指南》,前往:https://developer.aliyun.com/topic/devops,下载完整版电子书,了解阿里十年DevOps实践经验。

开发一个需求,需要先进行代码的编写和个人验证,验证功能符合预期之后,再提交代码,并进入到集成环境,进行进一步的验证及验收。而这个编码和验证的过程占据了整个需求交付的大部分时间,因此提高这部分工作的效率就显得至关重要。

问题

有什么因素降低了开发调试的效率呢?

给定下面一个系统,其中为了开发某个需求,修改了 A 和 D 这两个应用(这里的应用指的是一个可提供服务的一组独立进程加上可选的负载均衡,比如一个 kubernetes 下的 service 及其后端的 deployment)。

接下来看看为了本地调测这两个应用,会遇到什么问题。

本地难以启动整个系统

我们通常都在开发一个复杂系统中的一个应用,这个应用可能在系统的最前端,也可能在系统的中间位置,有时候为了端到端验证整个流程,需要把相关的应用都启动起来。

比如上图中的应用 A 为最前端应用,应用 D 处在中间位置,而黑框中部分是为了完整的测试这个需求而涉及到的应用,如果是 Java 应用,开发机上启动这样 5 个进程,就已经不堪重负了,而很多时候需要完整启动的应用数量会远大于这个数字。

依赖系统不稳定

既然不能把整个系统都在本地启动起来,那么本地就会一部分依赖于公共测试环境。虽然前面提到应该本地测试符合预期之后再把代码部署到测试环境,但不可避免的还是会出现一些 bug,导致测试环境不可用(这也是测试环境的价值所在,尽早的发现问题)。一旦依赖系统不可用,就无法正常的进行测试。

云原生开发模式下的测试环境的连通性

在基于 Kubernetes 的基础设施下,整个系统中大部分的应用通常不需要通过 Ingress 暴露到公网。如果你的测试环境是独立的 K8S 集群,那就意味着无法从本地无法访问到集群内的应用,那么依赖公共测试环境这件事情都无法进行,比如上图中 A->C,D->E,D->F 的依赖。

还有另外一种依赖,即上游应用对本地应用的依赖,比如 C->D 的依赖。但因为 C 是公共测试环境,不可以将所有的 C 对 D 的请求都打到本地来,这就需要某种机制来保证只有特定规则的请求会路由到开发本地的 D 应用。

外部依赖系统到开发环境的连通性

有一些测试链路需要接受一些外部依赖系统的回调,比如微信或者支付宝的回调等。而本地应用通常没有公网地址,这也给调试带来了一些困难。

中间件的隔离

分布式系统中经常会用到 RocketMQ 等消息中间件,如果使用了公共测试环境,就意味着 MQ 也是共用的,那么 MQ 的消息到底是应该被测试环境消费,还是某个个人的开发环境消费呢,这也是需要解决的问题。

高效本地开发

为了进行全流程的高效开发,应该尽量使用反馈比较快的验证方式,并及早发现问题,逐步进行更加集成,更加真实的测试。

一般来讲,一个开发过程可以经过下面的三个阶段:

1、编码+单元测试。在小的逻辑单元的层面保证正确性。
2、针对单个应用的集成测试,可能需要对依赖的应用进行 HTTP 级别的 mock。
3、结合公共测试环境进行完整的集成测试。

基于上面的三个阶段,可以使用以下的方式来解决前面提到的几个问题。

1、使用各个语言相应的测试工具(比如 JUnit)来进行单元测试。
2、使用 moco 等 HTTP Mock 工具来解决本地隔离验证的问题,完成单个应用的集成测试。
3、使用 kt-connect 和 virtual-environment 等工具来解决云原生基础设施下,本地和测试环境的互相连通性问题,及 http 请求链路的染色和路由。
4、使用 ngrok 等工具解决外部依赖调用本地应用的问题。
5、使用“主干稳定环境”作为公共测试环境,提高其稳定性。
6、使用中间件的染色隔离能力保证 http 请求之外的其它链路(比如消息)的染色和路由。

其中第 1、4 是成熟的技术,这里不再赘述。第 5、6 点会在后面的测试环境相关的章节中我们详细讲解。本文主要就第 2、3 点展开讲解。

单应用的集成测试方案

比如对应用 D 而言,测试范围如下图的橙色框所示:

应用本身的持久化等依赖使用真实的(一般使用本地 DB),但外部应用(应用 E、F)使用基于 HTTP协议的测试替身。这样就可以保证所有的依赖都是稳定的。并且也可以很方便的修改测试替身的行为,以进行特定场景的测试。

应用 D 依赖了两个应用:

1、org-service(应用 F):提供查询组织信息等能力
2、user-service(应用 E):提供查询用户信息等能力

这两个应用的访问地址配置在应用 D 的配置项中:

...
org-service-host: org-service
user-service-host: user-service
...

我们使用 docker compose + moco 的方案来讲解如何使用本地测试替身。

首先创建如下的目录结构:

├── Dockerfile
├── docker-compose.yml
├── moco-runner.jar
└── services├── org-service│   └── config.json└── user-service└── config.json

Dockerfile:

FROM openjdk:8-jre-slimARG SERVICEADD moco-runner.jar moco-runner.jar
COPY services/${SERVICE}/config.json config.jsonENTRYPOINT ["java", "-jar", "moco-runner.jar", "http", "-c", "config.json", "-p", "8080"]

docker-compose.yml:

version: '3.1'
services:service-f:ports:- 8091:8080build:context: .dockerfile: Dockerfileargs:SERVICE: org-serviceservice-e:ports:- 8092:8080build:context: .dockerfile: Dockerfileargs:SERVICE: user-service

services/org-service/config.json:

[{"request": {"uri": "/"},"response": {"text": "org service stub"}},{"request": {"uri": {"match": "/orgs/[a-z0-9]{24}"}},"response": {"json": {"name": "some org name","logo": "http://xx.assets.com/xxx.jpg"}}}
]

services/user-service/config.json:

[{"request": {"uri": "/"},"response": {"text": "user service stub"}},{"request": {"uri": {"match": "/users/[a-z0-9]{24}"}},"response": {"json": {"name": "somebody","email": "somebody@gmail.com"}}}
]

然后使用如下命令来启动两个依赖的应用:
docker-compose up --build
验证下本地测试替身的行为:

$ curl http://localhost:8092/users/111111111111111111111111
{"name":"somebody","email":"somebody@gmail.com"}
$ curl http://localhost:8091/orgs/111111111111111111111111
{"name":"some org name","logo":"http://xx.assets.com/xxx.jpg"}

然后再把应用 D 的依赖配置改成本地测试替身即可进行测试:

...
org-service-host: localhost:8091
user-service-host: localhost:8092
...

至此,我们得到了一个稳定的单应用的集成测试环境。当需要修改依赖的行为时,只需要修改相应应用的config.json 即可。

使用 docker-componse 和 moco 是一种实现单应用集成测试的方式,你可以根据项目的具体情况选择合适的工具和方案。

本地和公共测试环境的互访及链路隔离

完成单应用的集成测试之后,可以获得单个应用级别的质量信心,但更大范围的验证还是需要和真实的依赖集成在一起进行。

如上图所示,为了能够在本地按需启动应用(A 和 D),并复用测试环境的其他应用(C),就需要解决两个问题:

1、本地如何调用到公共测试环境的应用,即 A 如何调用到 C
2、公共测试环境如何调用到本地,即 C 如何调用到本地的 D

关于第一点,如果本地环境和测试环境的网络是直接可达的,则直接修改本地应用 A 的配置项即可。如果你使用了云原生的基础设施,那么就需要类似云效 kt-connect 之类的工具来进行打通,这里不再展开,有需求要的可以参看 kt-connect 的 connect 部分。

关于第二点,需要解决三个问题:

1、从测试环境的 A 发起的调用链,应该最终访问到测试环境的 D,而从本地环境的 A 发起的调用链,应该最终访问到本地环境的 D,互不影响。为了能够对这两种调用进行区分,需要对调用链进行“染色”,这里采用的染色的方式是在请求中加入一个额外的 header。
2、根据这个染色的标志,即“染色标”,进行路由。
3、一个调用链会贯穿多个应用,要保证在调用到不同的应用时,染色标要能够自动的传递下去。
关于第一点和第二点,在阿里巴巴内部有一套完整的方案进行染色和路由,这套方案不仅仅适用于 HTTP 链路,也适用于 RPC,异步消息等。而在开源领域,也有基于云原生基础设施的 kt-connect 可以用,使用kt-connect 的 mesh 功能就可以针对特定染色规则的调用链进行路由。

kt-connect 基于 istio 的 VirtualService 和 DestinationRule 来进行路由。其基本原理是在集群内新建一个影子副本的 service 和 deployment,然后提交一个应用 D 的 DestinationRule 资源,使得包含“local-env: true”header 的请求被路由到应用 D 的影子副本,然后应用 D 的影子副本再把请求转发到本地。在这个过程里,除了提交和更新 is t i o 相关资源的操作需要手动进行之外,其他的事情都可以使用ktctl mesh 命令来完成,详情请参看 mesh 最佳实践。

接下来解决第三点,染色标传递。即需要保证当本地的应用 A 把含有“local-env: true”header 的请求打到测试环境的应用 C 后,应用 C 继续访问应用 D 时候,请求中也应该包含这个 header。

一般的思路是在 Web 层的入口加一个 Interceptor,将染色标记录下来到一个 ThreadLocal 中,然后再出口的 HttpClient 层再从 ThreadLocal 中把这个染色标取出来,并填充到 Request 对象中。这里有一个需要注意的问题,因为染色是放在 ThreadLocal 中的,因此在一个 web 请求的处理中一旦遇到多线程的情况,就需要小心的把这个 ThreadLocal 的值传递到相应的子线程中。所有的应用都正确的将染色标传递下去,就可以保证染色标在全链路进行传递。

使用 kt-connect 的 mesh 方案加上全链路染色标的方案,就可以轻松的在本地按需启动应用,并进行开发调测。

总结

使用单元测试、单应用集成测试、端到端集成测试结合的方式进行本地调测,提高获得反馈的效率。
本地按需启动应用进行端到端集成测试的关键技术是:全链路染色和路由。在不同的基础设施下可以有不同的实现方式。

【关于云效】

云原生时代一站式DevOps平台,数十万企业都在用。支持公共云、专有云和混合云多种部署形态,通过云原生新技术和研发新模式,助力创新创业和数字化转型企业快速实现研发敏捷和组织敏捷,打造“双敏”组织,实现多倍效能提升。

立即体验

如何提升本地开发联调效率|阿里巴巴DevOps实践指南相关推荐

  1. 重磅发布!阿里云云效《阿里巴巴DevOps实践指南》

    简介:6月23日,在2021阿里巴巴研发效能峰会上,由阿里云云效团队20位专家共同撰写的<阿里巴巴DevOps实践指南>(以下简称指南)正式对外发布.本指南是阿里云云效团队对过去十年阿里巴 ...

  2. 代码评审|阿里巴巴DevOps实践指南

    编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>前往:https://developer.aliyun.com/topic/devops,下载完整版电子书,了解阿里十年 ...

  3. 阿里巴巴DevOps实践指南 | 数字化转型下,DevOps的根本目标是什么?

    简介:数字化转型是信息技术与产业的结合.需要转型的不仅仅是各个传统的产业,也包含信息产业本身,如互联网公司.DevOps 是数字化转型的重要组成部分,DevOps 的体系和实践也必须服务于数字化转型的 ...

  4. 阿里巴巴DevOps实践指南 | 为什么DevOps的必然趋势是BizDevOps?

    简介:从精益思想出发,我们可以看到DevOps的必然发展方向,那就是向业务侧延伸.业务是产品开发和运维的源头,完整的价值流必须从源头开始.这不是预测,而是正在发生的事实 编者按:本文源自阿里云云效团队 ...

  5. 阿里智能运维实践|阿里巴巴DevOps实践指南

    编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>前往:https://developer.aliyun.com/topic/devops,下载完整版电子书,了解阿里十年 ...

  6. 5种阿里常用代码检测推荐 | 阿里巴巴DevOps实践指南

    简介: 随着业务演进和团队扩张,软件规模和调用链路越来越复杂.如若没有良好的代码检测机制,只依靠功能性验证,团队技术债会越累越高,开发团队往往要花费大量的时间和精力发现并修改代码缺陷,最终拖垮迭代进度 ...

  7. 阿里巴巴如何进行测试提效 | 阿里巴巴DevOps实践指南

    编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>,扫描上方二维码或前往:https://developer.aliyun.com/topic/devops,下载完整版电 ...

  8. 开放下载!《阿里巴巴 DevOps 实践手册》

    简介:覆盖 DevOps 演进史.核心理念与阿里巴巴 DevOps 最佳实践的全方位解析手册,揭开阿里巴巴高效研发的秘密! 最新下载>><阿里巴巴DevOps 实践指南>了解详 ...

  9. 阿里巴巴DevOps实践手册 附下载链接

    今天和大家分享的有关阿里巴巴DevOps实践手册的内容,下拉文末获取网盘链接. 一.阿里巴巴 DevOps 文化浅谈 1.1 火遍全球的 DevOps 到底是什么? 1.2 如何利用 DevOps 进 ...

最新文章

  1. 在疫情防控一线,技术能发挥什么作用?
  2. 春节添彩 福州花卉市场现“买花潮”
  3. ITK:从测量列表创建直方图
  4. matlab randn 范围,请问randn产生的数据在什么范围内变化
  5. JAVA回调函数的例子_javascript : 回调函数例子
  6. OC 获取view相对位置_【全职业P4阶段世界BUFFS和药剂】BUFFS获取方法药剂自己查询出处...
  7. mql 查询多结果_详解Oracle分页查询概念、缘由及如何实现
  8. 超级鹰平台识别boss验证码
  9. 03. JavaMail 发送HTML邮件
  10. AI 四小龙之间没有战争
  11. Trunk详解(笔记)
  12. php deprecated是什么意思,php之Deprecated 问题å
  13. JSR 356 WebSocket (Java WebSocket 1.0) support is not available when running on Java 6. To suppress
  14. pygame: libpng warning: iCCP: known incorrect sRGB profile 报错
  15. linux 服务器搭建opvn
  16. uni-app云打包失败
  17. 量子统计:玻尔兹曼分布、玻色分布、费米分布
  18. 华为云服务器默认密码怎么修改,如何修改云服务器登陆密码
  19. nth-child和nth-of-type的区别
  20. python 画曲线(基本的坐标轴,刻度,网格,解决中文显示乱码)

热门文章

  1. GNSS相关网站汇总
  2. ARM 内联汇编-1
  3. Permute 3.5.14 小巧便捷的多媒体文件格式转换器
  4. 定积分及其应用知识点总结_高中数学知识点复习资料归纳整理:定积分和微积分基本定理...
  5. C 左移 和右移 计算
  6. 3. Fomula-Financial Market and Product
  7. layui from.render什么意思
  8. 大功率Inp半导体激光器
  9. 一文读懂什么是分布式文件系统
  10. erp服务器安装虚拟打印机,如何在云服务器上使用打印机