Jepsen:分布式系统最早的混沌框架

来源 | 混沌工程实践

作者 | 罗冈庭

头图 | 下载于ICphoto

Jepsen测试框架的工作模式和混沌工程的思想是一脉相承的。Jepsen测试框架可以在分布式系统上注入众多混沌事件,例如引入网络问题、杀死节点和生成随机负载等等,然后通过执行预先定义的测试操作,根据过程记录和结果分析,发现分布式系统(主要是数据库、协调服务和队列)中潜在的一致性问题。

Jepsen 是什么

根据CAP定理,一致性、可用性和分区容错性,分布式系统只能实现这三个关键属性中的两个。大多数分布式系统不会放弃分区容错性,一致性和可用性的权衡,像数据存储服务则偏向于一致性。

Jepsen致力于提高分布式数据库、队列和共识协调系统等的一致性。Jepsen是由凯尔·金斯伯里(Kyle Kingsbury)采用函数式编程语言Clojure编写的测试框架,用来验证分布式系统的一致性。Jepsen于2015年开源。(https://github.com/jepsen-io/jepsen)

Kyle也是开源分布式监控工具Riemann的创始人,可能大家没有听过Riemann。《监控的艺术》(The Art of Monitoring),这本书投入蛮多篇幅来介绍这款低延迟的监控系统。

Jepsen已被用来测试众多分布式系统,例如MongoDB、ElasticSearch和Zookeeper。

自2013年以来,Jepsen已经分析了二十多个业界知名的数据库、协调服务和队列,发现了副本分叉(replica divergence)、数据丢失(data loss)、过期读取(stale reads)、读偏序(read skew)、锁冲突(lock conflicts)等等多类型的一致性问题。(https://jepsen.io/analyses)

Clojure 的难度

Jepsen本身基于Clojure开发,想要深入了解该框架的内部实现以及上述业界知名分布式系统的Jespen测试代码,就需要学会Clojure。Clojure是一种基于JVM的函数式编程语言,跟Java可以进行很好的交互。Jepsen的作者Kyle也写过一篇关于Clojure入门相关的文章。(https://aphyr.com/posts/301-clojure-from-the-ground-up-welcome)

很多人听到函数式编程,就开始瑟瑟发抖,其实大可不必,因为对于Jepsen的使用者而言,看得懂,会修改现有的例子,往往都能满足大多数的需求,不过这确实在一定程度上影响了Jepsen在这个领域的应用范围。

这里就不详细介绍Clojure的安装和配置了。

Jepsen 的工作模式

如下图所示,Jepsen运行在控制节点(Control Node)上,测试过程中会启用生成器(Generator)进程、SSH客户端(Client)、克星(Nemesis)进程和检查器(Checker)进程。

以分布式数据库集群为例,Jepsen的工作大致包含以下几步:

  • Jepsen在控制节点(Control Node)上作为Clojure程序运行;

  • 部署需要测试的分布式数据库集群(Distributed System),确认其工作正常;

  • 控制节点启动进程,作为分布式数据库节点(DB Node)的SSH客户端;

  • 生成器(Generator)进程为每个SSH客户端生成具体要执行的读写操作;

  • 这些SSH客户端将在分布式数据库中执行这些读写操作;

  • 每个操作从启动到结束的过程都会记录下来;

  • 当读写操作进行时,克星进程(Nemesis)对分布式数据库进行故障注入,同样也是由生成器来调度和管理;

  • 测试完成,分布式数据库集群会被销毁。Jepsen使用检查器(Checker)进程对测试过程的历史记录进行分析,并生成最终的图表和报告。

Jepsen 与混沌工程

采用基于经验和系统的方法解决分布式系统在规模增长时引发的问题, 并以此建立对系统抵御这些事件的能力和信心。在受控实验中观察分布式系统的行为,借此了解系统特性,我们称之为混沌工程。

混沌工程是在分布式系统上进行实验的学科, 目的是建立对系统抵御生产环境中失控条件的能力以及信心。

前面我们了解了Jepsen的工作模式,这和混沌工程的思想是一脉相承的。

Jepsen可以在分布式系统上注入众多混沌事件,例如引入网络问题、杀死节点和生成随机负载等等,然后通过执行预先定义的测试操作,发现分布式系统(主要是数据库、协调服务和队列)中的一致性问题。

详细的Jepsen介绍文档可以参考这里:https://github.com/jepsen-io/jepsen/blob/main/doc/tutorial/index.md

Hello World 示例

今天,我们先以一个空白场景为例,感受下Jepsen的用法。

在容器中进行Jepsen测试,需要多种类型的容器配合部署:

  • jepsen-control: 控制节点,管理其他节点,创建和销毁,生成测试操作和故障注入场景

  • jepsen-nX: 目标分布式数据库集群(默认是5个节点)

  • jepsen-node: 克星节点,负责故障注入

下面的链接中提供了docker-compose up的方式,快速部署个Jepsen测试环境:https://github.com/jepsen-io/jepsen/tree/main/docker

完成部署之后,要在容器中运行 Jepsen 测试,则需要通过以下命令

$ docker exec-ti jepsen-control bash

进入jepsen-control节点,该容器中已经安装了Java和Clojure运行环境,以及lein(Clojure集成开发工具),然后就创建一个etcd的示例测试项目:

$ lein new jepsen.etcdemoGenerating a project called jepsen.etcdemo based on the 'default'template.Thedefaulttemplateis intended for library projects, not applications.To see other templates (app, plugin, etc), try`lein help new`.$ cd jepsen.etcdemo$ lsCHANGELOG.md  doc/  LICENSE  project.clj  README.md  resources/  src/  test/

像任何新的Clojure项目一样,项目文件夹下包含:

  • 一个空白的变更日志

  • 一个文档目录

  • 一份 Eclipse 公共许可证的副本

  • 一个 project.clj,说明了lein如何构建和运行代码

  • 一个描述文件

  • 一个resources目录,存放数据文件的地方,例如:要测试的数据库的配置文件。

  • 一个src目录,存有源代码

  • 一个test目录,里面是大多数 Clojure 库的测试约定,我们不会在这里使用它。

先对project.clj进行修改,指定项目的依赖项和其他元数据。添加一个:main的命名空间jepsen.etcdemo,这就是我们从命令行运行测试的入口。

除了依赖Clojure语言本身,我们还将引入2个依赖库:JepsenVerschlimmbesserung,后者用于与etcd的交互。

(defproject jepsen.etcdemo "0.1.0-SNAPSHOT":description "A Jepsen test for etcd":license {:name "Eclipse Public License":url "http://www.eclipse.org/legal/epl-v10.html"}:main jepsen.etcdemo:dependencies [[org.clojure/clojure "1.10.0"][jepsen "0.2.1-SNAPSHOT"][verschlimmbesserung "0.1.3"]])

我们来执行下lein run

$ lein runExceptionin thread "main" java.lang.Exception: Cannot find anything to run for: jepsen.etcdemo, compiling:(/tmp/form-init6673004597601163646.clj:1:73)...

回想下,刚添加一个:main的命名空间jepsen.etcdemo,里面现在还没有东西,我们需要在src/jepsen/etcdemo.clj中添加具体的测试操作。

(ns jepsen.etcdemo)(defn -main"Handles command line arguments. Can either run a test, or a web server for  browsing results."[& args](prn "Hello, world!" args))

我们再来执行下lein run

$ lein run hi there"Hello, world!"("hi""there")

可以跑起来了!

让我们使用jepsen.cli命名空间,简称cli,并将我们的main函数转换为Jepsen测试运行程序:

(ns jepsen.etcdemo(:require[jepsen.cli :as cli][jepsen.tests :as tests]))(defn etcd-test"Given an options map from the command line runner (e.g. :nodes, :ssh,:concurrency, ...), constructs a test map."[opts](merge tests/noop-test{:pure-generators true}         opts))(defn -main"Handles command line arguments. Can either run a test, or a web server for  browsing results."[& args](cli/run! (cli/single-test-cmd {:test-fn etcd-test})            args))

cli/single-test-cmdjepsen.cli提供,将会解析命令行参数,并调用:test-fn,该函数会返回一个包含Jepsen测试所需的所有信息映射。在这种情况下,测试函数etcd-test接受命令行参数,这里选择的是空测试,即noop-test

是时候跑一下测试看看了!

$ lein run test13:04:30.927[main] INFO  jepsen.cli - Test options:{:concurrency 5,:test-count 1,:time-limit 60,:nodes ["n1""n2""n3""n4""n5"],:ssh{:username "root",:password "root",:strict-host-key-checking false,:private-key-path nil}}INFO [2018-02-0213:04:30,994] jepsen test runner - jepsen.core Running test:...INFO [2018-02-0213:04:35,389] jepsen nemesis - jepsen.core Starting nemesisINFO [2018-02-0213:04:35,389] jepsen worker 1- jepsen.core Starting worker 1INFO [2018-02-0213:04:35,389] jepsen worker 2- jepsen.core Starting worker 2INFO [2018-02-0213:04:35,389] jepsen worker 0- jepsen.core Starting worker 0INFO [2018-02-0213:04:35,390] jepsen worker 3- jepsen.core Starting worker 3INFO [2018-02-0213:04:35,390] jepsen worker 4- jepsen.core Starting worker 4INFO [2018-02-0213:04:35,391] jepsen nemesis - jepsen.core Running nemesisINFO [2018-02-0213:04:35,391] jepsen worker 1- jepsen.core Running worker 1INFO [2018-02-0213:04:35,391] jepsen worker 2- jepsen.core Running worker 2INFO [2018-02-0213:04:35,391] jepsen worker 0- jepsen.core Running worker 0INFO [2018-02-0213:04:35,391] jepsen worker 3- jepsen.core Running worker 3INFO [2018-02-0213:04:35,391] jepsen worker 4- jepsen.core Running worker 4INFO [2018-02-0213:04:35,391] jepsen nemesis - jepsen.core Stopping nemesisINFO [2018-02-0213:04:35,391] jepsen worker 1- jepsen.core Stopping worker 1INFO [2018-02-0213:04:35,391] jepsen worker 2- jepsen.core Stopping worker 2INFO [2018-02-0213:04:35,391] jepsen worker 0- jepsen.core Stopping worker 0INFO [2018-02-0213:04:35,391] jepsen worker 3- jepsen.core Stopping worker 3INFO [2018-02-0213:04:35,391] jepsen worker 4- jepsen.core Stopping worker 4INFO [2018-02-0213:04:35,397] jepsen test runner - jepsen.core Run complete, writingINFO [2018-02-0213:04:35,434] jepsen test runner - jepsen.core AnalyzingINFO [2018-02-0213:04:35,435] jepsen test runner - jepsen.core Analysis completeINFO [2018-02-0213:04:35,438] jepsen results - jepsen.store Wrote/home/aphyr/jepsen/jepsen.etcdemo/store/noop/20180202T130430.000-0600/results.ednINFO [2018-02-0213:04:35,440] main - jepsen.core {:valid? true}Everything looks good! ヽ(‘ー`)ノ

我们可以看到,Jepsen启动了一系列SSH客户端进程,负责对数据库执行测试操作,还有就是启用了故障注入的克星进程。这里我们并没有执行任何操作,所以立即停止了。此后,Jepsen会将这个测试结果写到store目录中,并打印出一个简短的分析。

$ ls store/latest/history.txt  jepsen.log  results.edn  test.fressian

history.txt显示测试执行的操作,这里应该是空的,因为noop-test不执行任何操作;jepsen.log存有该测试的控制台日志;results.edn包含了对测试的分析;最后,test.fressian助力事后分析的测试原始数据,包括完整的机器可读的历史记录和分析结果。

若此时遇到SSH错误,应检查SSH客户端是否正常运行,并且是否已加载所有节点的密钥。

$ lein run test --help#object[jepsen.cli$test_usage 0x7ddd84b5 jepsen.cli$test_usage@7ddd84b5]-h, --help                                                  Printoutthis message andexit-n, --node HOSTNAME             ["n1""n2""n3""n4""n5"]  Node(s) to run test on--nodes-file FILENAME                                   File containing node hostnames, one per line.--username USER             root                        Usernamefor logins--password PASS             root                        Passwordfor sudo access--strict-host-key-checking                              Whether to check host keys--ssh-private-key FILE                                  Path to an SSH identity file--concurrency NUMBER        1nHow many workers should we run? Must be an integer, optionally followed by n (e.g. 3n) to multiply by the number of nodes.--test-count NUMBER         1How many times should we repeat a test?--time-limit SECONDS        60Excluding setup and teardown, how long should a test run for, in seconds?

最后,我们就可以销毁分布式系统集群的所有节点了。

结束语

本文我们介绍Jepsen测试框架的来历、基本的工作模式、与混沌工程的关系,也体会了一下Jepsen的Hello World示例。

虽然我们还没有真正选择一个分布式系统,进行实际的测试操作,也没有同时进行故障注入,但至少我们体验了一把Jepsen测试所需要的函数式编程语法。

后面我们会以一个具体的例子来详实地分享,如何使用Jepsen检验分布式系统的一致性问题。

   更多精彩推荐   
云上数据保护,你以为挡住黑客就够了?在这次采访中,Mendix 披露了低代码方法论DeVOpS 实战:Kubernetes 微服务监控体系还在担心无代码是否威胁程序员饭碗?

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

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

相关文章

Linux 命令操作手册

文章目录一、Boot项目前后台二、进程三、防火墙四、查看系统版本五、权限赋予六、远程同步文件七、目录八、文件九、解/压缩十 、大文件分割方案十一、查看文件中关键词出现的次数十二、添加/删除/修改/查看用户和用户组十三、寻找文件十四、清空文件内容十五、磁盘占用删除包含…

天猫国际通过Hologres进行排行榜的实时交互式分析

简介: 本文将会为您分享天猫国际如何通过Hologres实现计算、存储、服务统一的实时交互式分析。 作者:景闻 阿里巴巴数据技术及产品部数据技术专家 一.业务背景 天猫国际营销活动分析实时排行榜是在大促中帮助业务快速的分析商家或者品牌的交易和流量的…

官宣!《新程序员·开发者黄金十年》正式发布

“在互联网还不发达的时代,就是《程序员》伴我成长的。”“怀念啊,曾经《程序员》的日子。”“我是看着《程序员》长大的,大二时买了创刊号。”“这可是我们这一代人大学时候满满的回忆,也是当时寝室中传阅最多的书。”“每年的《…

OpenKruise:解放 DaemonSet 运维之路

简介: 我们希望 OpenKruise 让每一位 Kubernetes 开发者和阿里云上的用户都能便捷地使用上阿里巴巴内部云原生应用所统一使用的部署发布能力! 作者 | 王思宇(酒祝) 前言 OpenKruise 是阿里云开源的大规模应用自动化管理引擎&…

云原生数据湖解决方案打破数据孤岛,大数据驱动互娱行业发展

简介: 数据湖是以集中、统一方式存储各种类型数据,数据湖可以与多种计算引擎直接对接,我们使用OSS作为数据湖底座,数据统一存储在OSS中,有效消除了数据孤岛现象,多种计算与处理分析引擎能够直接对存储在数据…

三角形已知边长求高公式_五年级数学:“长方形、正方形、三角形、平行四边形、梯形” 知识重点、难点全解析,附习题!...

张老师 - 5年级(多品小学教育)里辛镇中心小学谭老师和冰溪镇县后山小学谭老师需要的这份学习资料现在分享。本资料已制作电子版下载码是:5odc7n2i多边形的面积知识点1公式长方形:周长(长宽)2 ;字母公式:C(ab)2 面积长宽&am…

阿里技术文档:Redis+Spring全家桶+Dubbo精选+高性能+高并发

最近花了很长的时间去搜罗整理Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档。今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技能了,遇到哪方面的问题了 直接打开文档学一学就好…

持续定义Saas模式云数据仓库+BI

云数据仓库概述 今天和大家一起探讨一下我们Saas模式下云数据仓库加上商业智能BI能有什么新的东西出来。我们先来看一下云数据仓库的一些概述。预测到2025年, 全球数据增长至175ZB, 中国数据量增长至48.6ZB。数据量暴涨这个前提下,我们看一下…

多项式拟合lm_R语言多项式回归

含有x和y这两个变量的线性回归是所有回归分析中最常见的一种;而且,在描述它们关系的时候,也是最有效、最容易假设的一种模型。然而,有些时候,它的实际情况下某些潜在的关系是非常复杂的,不是二元分析所能解…

AI和大数据下,前端技术将如何发展?

简介: 2010年前后,各种大数据应用进入爆发期。如果说之前的Web应用更多地是在“产生”数据,那在2010年之后,如何更好地“展现”数据则被提上了新的高度,很多前端技术也随之打开了新的篇章。本文作者结合自己的实践&…

漫话云计算,这次加了点儿剧情

“云计算”这个词相信大家都非常熟悉作为目前最热门的科技概念之一它频繁地出现媒体的报道中专家们也经常将它挂在嘴边为它摇旗呐喊那么,究竟什么是云计算呢?它到底有什么用?相比传统计算,它有什么特别之处?今天这篇漫…

阿里云数据湖解决方案全面满足数据需求,帮助企业释放数据价值

简介: 基于阿里云对象存储OSS构建的数据湖解决方案,可以全面满足数据的存储、离线分析、交互查询等各种业务诉求,帮助企业释放数据的价值 1、行业综述 游戏市场需求旺盛,行业景气度持续提升 2020年突如其来的疫情,使…

微服务学习专栏

文章目录一、 Springboot 开源项目推荐1. SmartAdmin2. SPTools3. el-admin4. RuoYi-Vue5. mall6. OA系统开源一、 Springboot 开源项目推荐 1. SmartAdmin 项目地址:https://gitee.com/lab1024/smart-admin 2. SPTools 项目地址:https://gitee.com/52…

云原生时代,应用架构将如何演进?

简介: 如何借助云原生技术来提升交付速度?云原生时代背景下,研发的关注点又会有哪些转变?阿里云高级技术专家许晓斌通过本文分享从 IaaS 上云时代到 PaaS 上云时代的应用架构演进方向,以及云原生技术与应用架构演进的关…

Serverless 对研发效能的变革和创新

简介: 对企业而言,Serverless 架构有着巨大的应用潜力。随着云产品的完善,产品的集成和被集成能力的加强,软件交付流程自动化能力的提高,我们相信在 Serverless 架构下,企业的敏捷性有 10 倍提升的潜力。 作…

查看mysql服务的可视化_Prometheus 监控Mysql服务器及Grafana可视化

Prometheus 监控Mysql服务器及Grafana可视化、mysql_exporter:用于收集MySQL性能信息。使用版本mysqld_exporter 0.11.0官方地址使用文档:https://github.com/prometheus/mysqld_exporter图标模板:https://grafana.com/dashboards/7362下载地…

SprinBoot 集成 Flowable/Activiti工作流引擎

文章目录一、 Flowable工作流引擎1. flow2. flowable3. cims4. RuoYi-flowable5. springboot-flowable-modeler6. flowable-diagram二、Activiti 工作流引擎2.1. RuoYi-Vue-Process2.2. RuoYi-Process2.3. ruoyi-vue-activiti2.4. activiti7-workflow2.5. JeeSite4 JFlow2.6. a…

持续定义Saas模式云数据仓库+实时分析

简介: 从实时分析的价值、场景和数据流程,以及用户对平台能力要求展开,讲述云数据仓库MaxCompute的产品能力优势 ,面对实时分析场景的能力演进要求。进而以实时分析典型场景的全数据流程处理、建模和分析的最佳实践,讲…

超 8 成软件存已知高危开源漏洞,奇安信发布《2021 中国软件供应链安全分析报告》

编辑 | 宋 慧 出品 | CSDN云计算 头图 | 付费下载于东方IC 2020年底,SolarWinds 遭受的大规模网络攻击,使得美国和多国政府在内的 18000 机构被影响。几乎每个月,软件供应链都在遭受黑客攻击。 而从软件端看,“检测发现&#xf…

前后端分离 常用工具汇总

文章目录一、数据框架1. vue2. react二、UI框架2.1. element2.2. element-plus2.3. Ant Design Vue2.4. Ant Design of React2.5. Bootstrap三、工具3.1. Fast Mock3.2. Easy Mock3.3. Mock语法/案例一、数据框架 1. vue https://cn.vuejs.org/ 2. react https://react.do…