etcd 和 MongoDB 的混沌(故障注入)测试方法

news2024/9/24 5:28:38

https://img-blog.csdnimg.cn/370f265df9904be9bfe366dffe402986.png

最近在对一些自建的数据库 driver/client 基础库的健壮性做混沌(故障)测试, 去验证了解业务的故障处理机制和恢复时长. 主要涉及到了 MongoDB 和 etcd 这两个基础组件. 本文会介绍下相关的测试方法.

MongoDB 中的故障测试

MongoDB 是比较世界上热门的文档型数据库, 支持 ACID 事务、分布式等特性.

社区上大部分对 MongoDB 进行混沌(故障)测试的文章大多都是外围通过对 monogd 或 mongos 进行做处理进行模拟的. 比如如果想要让 MongoDB 自己触发副本集切换, 可以通过一下这样一段 shell 脚本:

# 将副本集主节点进程挂死
kill -s STOP <mongodb-primary-pid>

# 挂死之后, 业务受损, MongoDB 在几秒到十几秒应该会进程主备切换
# 切换完成后, 业务能自动将连接切换到新的工作正常的主节点, 无需人工干预, 业务恢复正常
# 这里一般验证的是 Mongo Client Driver 的可靠性

上面提到的手段一般是系统层级的, 如果我们只是想要模拟某个 MongoDB command 命令遇到网络问题了, 怎么做?进一步想要进行更细粒度的测试. 其实 MongoDB 在 4.x 以上版本内部已经实现了一套可控的故障点模拟机制 -> failCommand.

在测试环境部署 MongoDB 副本集的时候, 一般可以通过以下方式启动这个特性:

mongod --setParameter enableTestCommands=1

然后我们可以通过 mongo shell 针对特定的 command 开启故障点, 例如针对一次 find 操作让其返回错误码 2:

db.adminCommand({
    configureFailPoint: "failCommand",
    mode: {
      "times": 1,
    },
    data: {errorCode: 2, failCommands: ["find"]}
});

这些故障点模拟是可控的, 成本相对于必直接在机器上搞破坏比较低, 也很适合融入持续集成自动化流程. MongoDB 内置的故障点机制还支持了很多的特性, 比如让某个故障概率发生、返回任意 MongoDB 支持的错误码类型等等, 通过该机制, 我们可以很方便的在单元测试和集成测试中验证我们自己实现的 MongoDB Client Driver 的可靠性.

如果想具体知道 MongoDB 支持哪些故障点, 可以详细查看 MongoDB 提供的 specification, 里面有提到针对 MongoDB 每一个特性, driver 可以使用哪些故障点进行测试.

MongoDB 官方提供的 go 实现的 dirver 代码仓库中也有不少的例子可以参考 https://github.com/mongodb/mongo-go-driver/blob/345ea9574e28732ca4f9d7d3bb9c103c897a65b8/mongo/with_transactions_test.go#L122.

etcd 中的故障测试

etcd 是一个开源的、高可用的分布式键值存储系统, 它主要用于共享配置和服务发现.

之前我们提到了 MongoDB 内置了可控的故障点注入机制方便我们做故障点测试, 那么 etcd 是否也提供了呢?

没错, etcd 官方也提供了内置的可控故障注入手段方便我们围绕 etcd 做故障模拟测试, 不过官方提供的可供部署的二进制分发默认是没有使用故障注入特性的, 区别于 MongoDB 提供了开关, etcd 需要我们手动从源码编译出包含故障注入特性的二进制出来去部署.

etcd 官方实现了一个 Go 包 gofail 去做 "可控" 的故障点测试, 可以控制特定故障发生的概率和次数. gofail 可以用于任意 Go 实现的程序中.

原理上通过注释在源代码中通过注释 (// gofail:) 去对可能发生问题的地方埋藏一些故障注入点, 偏于进行测试验证, 例如:

    if t.backend.hooks != nil {
        // gofail: var commitBeforePreCommitHook struct{}
        t.backend.hooks.OnPreCommitUnsafe(t)
        // gofail: var commitAfterPreCommitHook struct{}
    }

在使用 go build 构建出二进制之前, 使用 gofail 提供的命令行工具 gofail enable 可以取消这些故障注入相关代码的注释, 并生成故障点相关的代码,这样编译出的二进制可以用于故障场景的细粒度测试. 使用 gofail disable 去注释去除掉生成的故障点相关代码, 再使用 go build 编译出的二进制就可以在生产环境使用.

在执行二进制的时候, 可以通过环境变量 GOFAIL_FAILPOINTS 去唤醒故障点, 如果你的二进制程序是个永不停机的服务, 那么可以通过 GOFAIL_HTTP 环境变量在程序启动的同时, 启动一个 HTTP endpoint 去给外部测试工具唤醒埋藏的故障点.

具体的原理实现可以查看下 gofail 的设计文档 -> design.

值的一提的是 pingcap 重新基于 gofail 重新造了个轮子, 做了不少优化: failpoint 相关代码不应该有任何额外开销; 不能影响正常功能逻辑,不能对功能代码有任何侵入; failpoint 代码必须是易读、易写并且能引入编译器检测; 最终生成的代码必须具有可读性; 生成代码中,功能逻辑代码的行号不能发生变化(便于调试); 如果想要了解它的实现原理, 可以查看这篇官方文章: Golang Failpoint 的设计与实现 这篇深度剖析的博客也值得一读: 在 Go 中使用 Failpoint 注入故障

接下来我们看看如何在 etcd 中启用这些故障埋点。

编译出可供进行故障测试的 etcd

etcd 官方仓库的 Makefile 已经内置了对应的指令帮我们快速编译出包含故障点二进制 etcd server. 编译步骤大致如下:

git clone git@github.com:etcd-io/etcd.git
cd etcd

# 激活故障点注释
make gofail-enable
make build
# 还原代码
make gofail-disable

经过如上步骤之后, 编译好的二进制文件直接可以在 bin 目录下可以看到, 让我们启动 etcd 看一下:

# 开启通过 HTTP 激活故障点的方式
GOFAIL_HTTP="127.0.0.1:22381" ./bin/etcd

使用 curl 看下有哪些故障点可以使用:

curl http://127.0.0.1:22381

afterCommit=
afterStartDBTxn=
afterWritebackBuf=
applyBeforeOpenSnapshot=
beforeApplyOneConfChange=
beforeApplyOneEntryNormal=
beforeCommit=
beforeLookupWhenForwardLeaseTimeToLive=
beforeLookupWhenLeaseTimeToLive=
beforeSendWatchResponse=
beforeStartDBTxn=
beforeWritebackBuf=
commitAfterPreCommitHook=
commitBeforePreCommitHook=
compactAfterCommitBatch=
compactAfterCommitScheduledCompact=
compactAfterSetFinishedCompact=
compactBeforeCommitBatch=
compactBeforeCommitScheduledCompact=
compactBeforeSetFinishedCompact=
defragBeforeCopy=
defragBeforeRename=
raftAfterApplySnap=
raftAfterSave=
raftAfterSaveSnap=
raftAfterWALRelease=
raftBeforeAdvance=
raftBeforeApplySnap=
raftBeforeFollowerSend=
raftBeforeLeaderSend=
raftBeforeSave=
raftBeforeSaveSnap=
walAfterSync=
walBeforeSync=

知道了故障点, 就可以针对指定故障设置故障类型, 如下:

# beforeLookupWhenForwardLeaseTimeToLive 故障点处 sleep 1 秒
curl http://127.0.0.1:22381/beforeLookupWhenForwardLeaseTimeToLive -XPUT -d'sleep(10000)'
# 查看故障点状态
curl http://127.0.0.1:22381/beforeLookupWhenForwardLeaseTimeToLive
sleep(1000)

故障点的描述语法见: https://github.com/etcd-io/gofail/blob/master/doc/design.md#syntax

至此, 已经可以利用 etcd 内置的故障点做一些故障模拟测试了, 具体怎么使用这些故障点可以参考下 etcd 官方的集成测试实现 -> etcd Robustness Testing. 通过故障点名称搜索相关代码即可.

除了上述这些 etcd 内置的故障点, etcd 的官方仓库也提供了一份系统级的集成测试例子 -> etcd local-tester, 它模拟了 etcd 集群模式下的节点宕机测试.

好了, 本文的分享, 到此暂时结束啦 ღ( ´・ᴗ・` )~

小广告插播: 最近维护了可以维护多个 etcd server、etcdctl、etcductl 版本的工具 vfox-etcd, 你也可以用它来在机器上安装多个包含 failpoint 的 etcd 版本进行混沌 (故障模拟) 测试哦~

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1701570.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】 虚拟机可以ping通主机 主机却ping不通虚拟机 解决方法

我当时初学linux&#xff0c;需要虚拟机联网&#xff0c;且虚拟机和windows需要能相互ping通&#xff0c;我当时就是虚拟机一切正常&#xff0c;虚拟机显示有网可以ping通百度&#xff0c;也可以ping通windows&#xff0c;但是windows就是ping不通虚拟机&#xff0c;这个问题困…

容器组件:页面和自定义组件生命周期(HarmonyOS学习第五课)

页面和自定义组件生命周期 先明确自定义组件和页面的关系&#xff1a; 自定义组件:Component装饰的UI单元&#xff0c;可以组合多个系统组件实现U的复用。 页面:即应用的UI页面。可以由一个或者多个自定义组件组成&#xff0c;Entry装饰的自定义组件为贞面的入口组件&#xf…

海信电视刷机以及简化操作经验介绍

刷机 强制U盘刷机 准备一个U盘&#xff0c;U盘格式化成 FAT32 格式。下载对应的刷机包&#xff0c;将 TargetHis 拷贝到u盘根目录关闭电视电源启动电视&#xff0c;并且不断的按下音量‘-’按键等待刷机就可以了 能开机 能开机的话就1.2一样&#xff0c;进入系统后&#xf…

03. Spring 事务管理

文章目录 1. Spring 事务管理简介2. Transactional 注解属性信息3. Transactional 简单使用4. Transactional 使用注意事项4.1 正确指定事务回滚的异常类型4.1.1 Java 异常继承体系 4.2 Transactional 注解应用在 public 方法或类上才有效4.3 正确设置 Transactional 的 propag…

【Spring】深入理解 Spring 状态机:简化复杂业务逻辑的利器

前言 在软件开发中&#xff0c;有许多场景需要处理状态转换和状态驱动的逻辑&#xff0c;比如订单处理、工作流程管理、游戏引擎等。Spring 状态机&#xff08;Spring State Machine&#xff09;是 Spring Framework 提供的一个强大的模块&#xff0c;用于帮助开发人员轻松构建…

【VTKExamples::Utilities】第二期 AnimationScene

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例AnimationScene,并解析VTK中动画的基本框架,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ…

OSCP学习,布置你的Kali Linux

为什么要写这篇文章&#xff1f; 我是一个OSCP学习者&#xff0c;以教促学。同时也能让各位入门的师傅们更好的了解OSCP这门课程。本人文笔不太好&#xff0c;如果有什么写的不对的地方&#xff0c;师傅们多多指正。 参考资料&#xff1a; OSCP 考试电子书 Linux Basics for…

微信小程序毕业设计-跑腿系统项目开发实战(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

深度学习之加宽全连接

1.Functional API 搭建神经网络模型 1.1.利用Functional API编写宽深神经网络模型进行手写数字识别 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.model_selection import train_test_spli…

工程技术SCI期刊,中科院4区,收稿范围非常广泛,审稿快易录用!

一、期刊名称 CMES-Computer Modeling in Engineering & Sciences 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;工程技术 影响因子&#xff1a;2.4 中科院分区&#xff1a;4区 三、期刊征稿范围 本期刊在工程与科学的计算机建模领域发表具有合理永…

python中的空语句以及对于条件语句的总结

if条件&#xff1a; 代码块 if条件&#xff1a; 代码块1 else&#xff1a; 代码块2 if条件1&#xff1a; 代码块1 elif条件2&#xff1a; 代码块2 else&#xff1a; 代码块3

2016届蓝桥杯大赛软件类国赛Java大学B组 愤怒小鸟 数学模拟

注意开浮点数 ​​​​ import java.util.Scanner;public class Main {static Scanner scnew Scanner(System.in);public static void main(String[] args) {double t0;int cnt0;double distance1000;while(distance>1){//相撞时间tdistance/60.0;distance-t*20;cnt;}Syste…

梭住绿色,植梦WILL来,容声冰箱“节能森林计划”再启航

近日&#xff0c;容声冰箱再度开启了“节能森林计划”绿色公益之旅。 据「TMT星球」了解&#xff0c;此次活动深入到阿拉善荒漠化地带&#xff0c;通过实地考察和亲身体验&#xff0c;见证容声了“节能森林计划”项目的持续落地和实施效果。 2022年&#xff0c;容声冰箱启动了…

IP地址在广告行业中的重要地位

新时代&#xff0c;广告已经成为了企业推广产品的必要手段&#xff0c;而企业想要广告效果好&#xff0c;就要做到精准投放营销广告&#xff0c;将“花钱”的广告精准送到产品的受众用户面前&#xff0c;让收益大于花销&#xff0c;而归根究底就是广告转化率与回报率是否达到预…

Kivy 项目51斩百词 6 播放读音

为了给小喇叭图像绑定点击事件&#xff0c;实现当用户点击按钮时&#xff0c;触发该事件对应的回调方法。 在方法内对于不同的系统Kivy使用不同的播放语音方法&#xff0c; 对于Windows系统 使用SoundLoader播放语音&#xff0c; 对于其他的Unix系统 使用Pyjnjus播放…

PawSQL: 企业级SQL审核工具的新玩家

随着数据库应用在企业中的广泛使用&#xff0c;确保SQL代码质量的重要性日益凸显。现有的SQL审核工具很多&#xff0c;包括Yearning、goInception、Bytebase、爱可生的SQLE、云和恩墨的SQM等等&#xff0c;但是它们或者规则覆盖度、或者是在正确率等方面存在明显不足&#xff1…

Halo Theme AirCloud 主题文档

发现一款简洁的halo主题 Halo Theme AirCloud 主题文档 | LogDicthttps://www.logdict.com/archives/AirCloud

2-Django项目进阶--继续学生管理系统

目录 项目框架: urls.py views.py modules.py class_data.html add_and_modify.html add_stu.html 笔记: 继承语法 模板继承总结&#xff1a; 班级添加 add_and_modify.html 修改添加公用一个页面即可 views.py 班级修改 views.py url.py 班级删除 views.py…

牛客热题:寻找第K大

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;寻找第K大题目链接方法一&#…

面试官:讲讲为什么SpringBoot的 jar 可以直接运行?

Spring Boot 是一个用于简化 Spring 应用程序开发的框架&#xff0c;它通过约定优于配置和大量的自动化配置&#xff0c;使得开发者可以更轻松地创建和部署 Spring 应用程序。一个特别引人注目的特性是 Spring Boot 应用可以打包成一个可执行的 JAR 文件&#xff0c;并且可以直…