乐趣区

关于测试:混沌工程推动可观测性的最佳实践-IDCF

本文中,咱们应用 DDD 领域建模的办法,设计了一个正当且简单的微服务叫车零碎,并在该零碎之上,利用 OpenTelemetry 进行了可观测性结构实际,最初采纳“强化混沌工程”的方法论,借助故障注入伎俩,实现了用于验证可观测性价值的最佳实际,并将游戏冲关的玩法融入软件开发的生命周期中,晋升利用的排障能力,以此升高零碎的 MTTR。

一、一个类 Uber 叫车试点利用

为了达到利用可观测性结构的成果,须要设计一个足够简单的试点利用,这里我抉择了这个类 Uber App 的设计和开发。

1.1 领域建模

首先,通过畛域驱动设计 DDD 的事件风暴,集众人之力实现该试点利用的畛域模型设计:

随后察看畛域中反复呈现的名词,找出限界上下文:

这样,类 Uber 叫车试点利用的畛域模型建模结束。

1.2 微服务架构设计

接着,咱们持续设计试点利用微服务化的零碎架构:

类 Uber 叫车试点利用有五个微服务,其中四个是由限界上下文衍生进去的,包含:

  • User 乘客
  • Match 叫车匹配
  • Trip 载客旅程
  • Payment 领取金流

另外加开了 broker-service,作为 Websocket 的对立进口。

微服务之间的通信机制,除了最间接的 RESTFul API,即上下游调用关系之外,也应用了 RabbitMQ 作为音讯队列将畛域事件无效播送到各服务去。

到了这边,类 Uber 叫车试点利用的设计也已趋于残缺,接下来就是实现。

1.3 Java Spring Boot 实现

应用 Java Spring Boot,遵循 Clean Architecture,最初花了一个月的工夫将后端残缺开发进去,共计大概 7000 行代码。

本文并不会深刻开展 Clean Architecture 的开发过程,有趣味的敌人可参考:https://github.com/Johnny8508…

二、OpenTelemetry 结构可观测性

2.1 可观测性概念的回顾

平时在开发环境中,遇到 Bug 的时候为求不便,都会开启调试器,借助中断来确认利用的行为是否合乎预期,然而,一旦利用部署到各环境中,便不能再应用调试器来察看利用的行为了。

所谓的可观测性,指的是利用在被部署到某个线上环境后,其自身还能透过“某种机制”来让开发人员,便捷地观测利用自身在线上“各个工夫点”的行为。

其中,Trace 记录着每个性能残缺的执行过程。因为执行过程会充斥着「上下游的调用关系」,联合起来就造成了一棵树。

那么,在技术上到底该如何出现?

手动剖析:

Grafana 出现:

2.2 OpenTelemetry 的新尝试

OpenTelemetry 的创造并非要解决新的问题,而是一个在可观测性三大支柱的需要下,实现繁多规范的框架。

咱们决定要尝试 OpenTelemetry 这一项 CNCF 近期推出的技术框架。

咱们先来看一下在以前,咱们都是如何做到分布式链路追踪的?

OpenTracing + Jaeger

以 OpenTelemetry 的设计观点来看,这种“大同小异”便有了能够施行统一标准的可行性。

在利用代码中,应用 OpenTelemetry SDK 来进行数据采集,下一步 Exporter 会将采集到的数据如:log/trace/metrics,用配置好的格局传递到 Agent 去,Agent 只是作为数据传递的中介,最初会再提供给 Collector。

为了要在利用中做分布式链路追踪,以往咱们都必须间接依赖厂商链路追踪产品的 SDK 来去埋点,但如此一来,将来如果决定要更换厂商时,则利用会有很大一部分须要重写。

OpenTelemetry 表演的就正是那一层形象的标准接口,如果利用依赖的是 OpenTelemetry 的 API,那将来要更换厂商时,就只须要扭转 OpenTelemetry 的配置就行,任何一行代码都不须要重写。

2.3 Java Agent 的主动采集

首先要先到 Github 下载 OpenTelemetry 最新释出的 Java Agent JAR。

https://github.com/open-telem…

接下来只须要将这个 JAR,在 Dockerfile 中将其 COPY 到镜像中,而后在 CMD 中无关 Java 的执行指令中,增加 javaagent 参数,将其指向 JAR 的地位,一并执行就行。

此外,还须要把追踪零碎一并部署起来,例如:Jaeger 或 Grafana Tempo。

根本范例可参考:https://github.com/Johnny8508…

一行代码都不必写,就可能产生出以下的 Trace 了:

以 Java Agent 形式执行的 OpenTelemetry,开发人员不再须要亲自埋点,不须要对链路追踪零碎有任何的认知,更不须要为此写任何一行代码。

OpenTelemetry 会寻找所有被标注上 @RestController 的物件,并在其每个 RESTFul 办法调用之前,被动进行数据采集,帮忙埋下适当的 Trace。

2.4 定制化采集

在体验到主动采集的弱小之后,大家心中浮现的第一个问题必定是如果我要定制化采集的话,要怎么办?

  • 第一种办法:由环境变量去设置 include / exclude 的类别或办法。
  • 第二种办法:应用 @WithSpan 来减少想要被放进 Trace 的办法。

以类 Uber 试点利用为例,有两个 POJO 物件:StartDriving 和 FindCurrentTrip,也想要被退出到 Trace 之中。

因为这两个物件只是单纯的 POJO,因而在预设的状况并不会被 OpenTelemetry 捕捉,为了将其退出到 Trace 之中,只须要其办法上加上 @WithSpan,就可能失去以下的后果:

咱们借助弱小的 OpenTelemetry in Java,很不便地实现了类 Uber 试点利用的可观测性结构。然而,以 SRE 的观点来看:

始终以来,SRE 都心愿可能最小化可观测性结构实际,以缩小其所带来的额定保护老本。

因而,咱们须要一种新的最佳实际,来证实可观测性结构的价值。

三、推动可观测性的最佳实际

通过了思考与设计,最初我参考了混沌工程的精力,开发出一个办法,能够通知我“目前的可观测性实际是否仍有缺点”?我把这个办法称之为“强化混沌工程”。

3.1 叫车流量的自动化模仿

然而,目前仅有一个类 Uber 的叫车零碎,还须要模仿乘客和司机的行为,来自动化地产生正当的叫车流量。

如上所附的动画所示,在通过数日的开发后,终于做出了一个简略的自动化叫车流量产生零碎。动画中出现的是五个司机和一个乘客的状况模仿。

序号 形容
1 乘客进行叫车匹配
2 零碎实现匹配,并且匹配到了某一司机
3 该名司机开始此次载客服务,并且朝着乘客的上车地点开车,挪动的过程中一直地向伺服器更新本身座标
4 乘客进行叫车匹配
5 零碎实现匹配,并且匹配到了某一司机
6 该名司机开始此次服务,并朝着乘客的上车地点开车,挪动的过程中一直地向服务端更新本身座标
7 乘客一直接管到司机最新的座标
8 司机到达乘客的上车地点,确认乘客上车后,司机将状态调整成“已上车”
9 司机开车返回目的地,挪动的过程中一直地向服务端更新本身座标
10 司机到达乘客欲返回的目的地,完结了服务
11 叫车流程完结,乘客将本人的座标更新到了随机的地位并开始了下一次的叫车匹配

看似简略的叫车流程,其背地的工作其实是必须由五个微服务以及 RabbitMQ 来合作实现的,当初咱们曾经可能发明大量且正当的叫车流量,总算能够来开始实际“强化混沌工程”了。

3.2 强化混沌工程

从 SRE 的视角上,可观测性结构的价值在于,咱们要花多少工夫才可能觉察并修复好生产零碎发现的问题,即 MTTR。

当初曾经有了“自动化叫车流量生成器”,也有评判可观测性结构的规范 MTTR,那剩下我最缺的就是“故障”了。

微服务等分布式系统在开发和运维上带来更高的门槛和复杂度,因而混沌工程便也开始被一直提倡。讲白一点,混沌工程就是“有目的地看待测系统搞破坏来提前揭发零碎的问题”。

为了揭发零碎的问题,咱们须要先看待测系统定义其稳态。以类 Uber 叫车试点利用来说,稳态便是“可能残缺且顺畅地执行每一个叫车流程”。

借鉴了混沌工程的思维,将其使用到可观测性场景中的话,则是“要有目的地在零碎中搞破坏来提前揭发可观测性结构的缺点”。

对此,因为应用场景较为非凡,是否有现存的第三方工具,可能满足类 Uber 叫车试点利用定制化的混沌场景,我并没有太大的自信,因而我决定本人实作一个可能实现混沌工程的技术架构,以下图所示:

新开了一个服务在图正地方,称之为 Chaos-Server。

而在利用各个服务中都会执行一个 Chaos Client,即 Chaos Agent。

Chaos-Server 和各个 Chaos-Client 相互沟通,传递指令,来实现整个混沌工程的流程。

咱们只须要在 Chaos 的操作页上对 Chaos-Server 下达命令就好。

3.3 冲关游戏的根本玩法

咱们把混沌工程的流程设计成了一款冲关游戏,上面是根本的玩法:

序号 步骤形容
1 部署好 Chaos-Server 和 Chaos-Client,启动自动化叫车流量生成器。
2 浏览 Chaos 操作页 /api/chaos,这个页面能够用来对 Chaos-Server 下达指令。
3 开始一个新的关卡:每一个关卡都能够由一串随便的字串来产生。
4 调用 API,如 /api/chaos/fun/56a8d709-9c22-489e-b44e-6d86f81796b2,其中的随便字串就是新关卡的惟一标识。
5 一群特定未知的 Chaos 就被埋好在利用的各个服务中了。
6 接下来持续在 Chaos 操作页上进行,操作页上会显示所有候选的 Chaos 名单,并且还会显示在这些 Chaos 中,有几个真的被激活了。
7 冲关开始后,自动化叫车流量生成器便会进入到“不稳固”的状态,因为 Chaos 的缘故,叫车流程将会受到影响而被阻断。因而咱们能够开始进行排障了。
8 在排障过程中,利用可观测性结构去察看利用行为,看看是否在最短的工夫内找出问题来。
9 一旦找到任何潜在的问题,对照 Chaos 操作页上的名字,抉择最可疑的那一个将其杀掉。
10 因为 Chaos 的名字间接以毁坏的内容进行命名,因而咱们能依据名字来去进行推测。
11 如果杀掉胜利,则 Chaos 的数量会少一个。反之,则会显示讯息:”You are mis-killing trip.SaveTripDelay, he is not the mole!”。
12 反反覆覆地玩耍,直到将所有 Chaos 赶尽杀绝为止。
13 如果最初发现无奈通关,则代表可观测性不够残缺,此时应该要记下笔记,对原先的稳态假说进行修改,并再次进行同一个关卡。

3.4 体验一次真正的冲关游戏

首先到 Grafana 的仪表盘上,能够看到三个根本面板:上方为 Metrics,包含:左上为即时的叫车匹配数量,右上为利用中的谬误数量;而下方则显示即时的 Logs。

开始一个新的关卡 56a8d709-9c22-489e-b44e-6d86f81796b2:

发现叫车流程整个卡住了,看来,Chaos 是真的开始在搞破坏了…。

一段时间之后,便在 Slack 频道上收到了一个谬误告警,通知咱们是时候去排障了。

同时也在面板上发现上方叫车匹配的数量急剧下滑,而下方也开始产生出了谬误日志:

搜寻带“ERROR”的日志,应用 Loki 的查问语法:

点击其中一个谬误日志,并且从日志的 traceID 栏,间接开启右半部 Jaeger 的 trace 页面。

间接从 trace 上察看,能够看到整个微服务的上半部是顺利的,但到下方调用 /api/drivers/{driverId} 这个 API 时产生了谬误。

同时,察看这个 trace 的执行工夫,居然高达了 12 秒!发现瓶颈为 /api/users/{userId} 这个 API。

点击 span 能够看到更多详细信息,而从 DriverController.setDriverStatus 这个办法的 span 中能够看见 exception.message 明火执仗地通知你,它就是 Chaos!

回到操作页面上,把对应到的两个 Chaos 杀掉:

  • user.SetDriverStatusAPIBlocked
  • user.FindUserDelay

杀掉完两个坏蛋之后,从页面上能够看到接下来只剩下 2 个 Chaos。

从这之后回去看叫车流程,会发现错误仿佛曾经隐没,然而整个叫车流程还是卡到不行。因而接下来必须要来做性能调优了。

这一步,到 Jaeger 这个 data source 下来操作,搜查在 match service 中近期的 traces,并且应用执行工夫来从大到小排序。从搜查后果上来看,会发现一个显著的效力瓶颈,居然有一堆 trace 的总执行工夫都高达六秒!点击左侧的 traceId,来导览到 trace 页面。

留神到 FindAvailableDrivers 有性能瓶颈,执行工夫高达 6 秒,这相对是 Chaos 搞的鬼。到 Chaos 操作页上将其杀掉!

接下来咱们就只剩下最初一个 Chaos 了。此时看叫车流程,性能感觉好了一些,然而整个停顿还是很迟缓,重复使用雷同的手法来排序 traces,但这一次咱们针对 user service。从这一次的搜查后果中,咱们便留神到了有许多的 traces,居然都花了长达 3 秒的工夫。

发现性能瓶颈可能在 UpdateLatestLocation,乘客或司机在旅程行驶中,会一直地调用它来更新本身的座标。如果 Chaos 对这个调用增加了提早,也难怪叫车流程会如此迟缓了。

最初,咱们就不用留情地把最初一个 Chaos 给杀掉。

游戏完结后,回去看叫车流程,会发现整个叫车流程的顺畅度又回来了!

四、结束语

本文中,咱们应用 DDD 领域建模的办法,设计了一个正当且简单的微服务叫车零碎,并在该零碎之上,利用 OpenTelemetry 进行了可观测性结构实际,最初采纳“强化混沌工程”的方法论,借助提前揭发实际瑕疵的故障注入伎俩,实现了用于验证可观测性结构价值的最佳实际形式,以游戏冲关的玩法融入软件开发的生命周期中,晋升咱们对利用的排障能力,以此升高可观测性结构的 MTTR。

起源:混沌工程实际

作者:水球潘 /JohnnyPan

申明:文章取得作者受权在 IDCF 社区公众号(devopshub)转发。优质内容共享给思否平台的技术伙伴,如原作者有其余思考请分割小编删除,致谢。

IDCF 社区共创读书会 首期汇报,每周四晚 8 点, 冬哥有话说 收费直播,关注公众号回复“共读”获取直播地址

  • 8 月 19 日,共读《思考,快与慢》
  • 8 月 26 日,共读《DevOps 实际指南》
  • 9 月 2 日,共读《麻利无敌之 DevOps 时代》
退出移动版