当前位置: 首页 > 科技观察

目前运维测试领域有哪些新技术?

时间:2023-03-22 00:06:25 科技观察

我觉得对待测试的态度是区分普通程序员和优秀程序员的重要标准。现在我们的程序和服务越来越大,单靠单元测试TDD之类的已经很难保证质量了,但是这些都是baseline,所以今天聊点新的话题。在谈论测试之前,让我们问问自己,为什么我们需要测试?当然是找bug了。看起来这是废话,但是仔细想想,如果我们能写出没有错误的程序,那不是很好吗?何必。但是100%无bug肯定是不够的,那么有什么办法可以尽可能的提高我们程序的质量呢?比如我想到一个Raft优化算法。与其等着实现再测试,不如在写代码之前就知道算法理论上有没有问题?其实是有办法的,就是形式化证明技术,比较常用的是TLA+。1.TLA+TLA+背后的想法很简单。TLA+会通过自己的一套DSL(符号很接近数学语言)来描述程序的初始状态和后续状态之间的转换关系,同时根据你的业务逻辑来定义这些。状态切换中的不变量,然后TLA+的TLC模型检查器穷举状态机所有可达状态,在穷举过程中不断检查不变量约束是否被打破。举个简单的例子,最简单的分布式事务的两阶段提交算法,对于TLA+Spec来说,需要你定义初始状态(比如事务要操作的key,有多少并发客户端等),以及然后定义Jump操作之间的状态(Begin/Write/Read/Commit等),最后定义不变量(例如,任何处于Committed状态的写操作必须根据提交时间戳排序,否则Read操作不得读取脏数据等),写入后放入TLCChecker运行,等待结果即可。然而,我们生活在一个不完美的世界,即使你写出完美的证明,也很难保证你是对的。首先,Simulator没有办法模拟无限多的患者和并发,通常是三到五个;第二,你可能会看到一般的TLA+宣传文章不会告诉你Spec的关键是Defineaninvariant。如果不变量定义不完全,或者定义错误,则证明无效。因此,我认为形式化验证的意义在于增加工程师在写代码前的信心,在写证明的过程中对算法有更深入的理解。另外,如果在TLCChecker上出现异常就更好了。目前PingCAP应该是国内唯一一家使用TLA+证明关键算法并开源证明的Spec的公司。您可以参考pingcap/tla-plusRepo。2.混沌工程如果不存在完美的证明,那么确定性检验存在吗?我记得大约在2015年,在PingCAP成立之前,我看到了FoundationDB的介绍,介绍他们的Deterministic测试。简单来说,他们使用自己的IO处理和多任务框架Flow,将代码逻辑与操作系统的线程和IO操作解耦,利用集群模拟器实现bug发生时的事件时序100%重现.准确的模拟出装置的各种异常情况,确实很完美。但是考虑到现实,我们选择使用的编程语言主要是Go,像Flow这样的东西很难或者说没有必要去做。所以我们选择从另一个方向来解决这个问题,提高分布式环境下bug的重现率,容易重现的bug也能轻松解决。这个想法也是近几年很火的混沌工程。做好混沌工程的几个关键点:定义稳态,记录正常环境下的工作量和关注的重要指标。在定义了系统的稳态后,我们将其分为实验组和控制组进行实验,并确认在理想的硬件条件下,无论实验组如何操作,最终都会回到稳态。开始破坏底层操作系统和网络,重复实验,观察实验组是否会回到稳定状态。道理大家都懂,但实践中最大的问题是如何将整个过程自动化。究其原因:一是依赖人工的效率很低;其次,正统的ChaosEngineering强调在生产环境中运行,如何控制爆炸半径也是一个比较重要的问题。先说第一个问题。在混沌工程实践的早期,PingCAP通过物理机上的脚本来启动和停止服务。所有的实验都需要人工完成,耗时耗力,效率很低,而且在资源利用上也很不合理。我们觉得这个问题正是K8s非常擅长的,所以我们基于K8s开发了一个自动化测试平台,内部叫Schrodinger,镜像TiDB集群的启停,也使用TiDB自带的CI/CD和自动化测试casesManagement和FaultInjection是统一的。这个项目还催生了一个有趣的子项目ChaosOperator:我们通过CRD来描述Chaos的类型,然后在不同的物理节点上启动一个DaemonSets。这个DaemonSets负责干扰Pod,并向相应的Pod中注入Sidecar。帮助我们注入错误(比如使用Fuse模拟IO异常,修改iptables创建网络隔离等),销毁Pod。我们还计划在不久的将来开源ChaosOperator。第二个问题,在我看来,ChaosEngineering还是不够。在我们对测试和质量的长期研究中,我们发现提高测试质量的关键是如何发现更多的测试工作负载。早期我们非常依赖MySQL和相关社区的集成测试。这个数字大约是数千万。这个决定使我们能够在确保质量的同时快速迭代,但即使这样还不够。我们也在向学术界寻求答案。比如引入并通过官方的JepsenTest,然后比如通过SQLfuzz自动生成合法的SQL语句加入测试集。总之,相对于写业务逻辑,在分布式环境下写测试+写测试框架可能省力一点,甚至多很多(代码量的话,TiDB的测试相关的代码行数可能比内核代码行数多一个数量级),这是一个非常值得研究和投资的领域。另一个问题是如何通过测试发现性能回归。一个叫benchbot的机器人每天都在我们的测试平台运行,每天的回归测试会自动运行性能测试来对比每天的结果。通过这种方式,我们的工程师可以快速知道哪些变化导致了性能下降,并得到长期的性能变化趋势。3.说完eBPF测试,另一个相关话题是profiling和distributedtracing。可以通过查看Google的Dapper和开源实现OpenTracing来理解跟踪,因此我将重点放在分析上。这几年比较关注eBPF(extendedBPF)技术。试想一下,以前我们要开发一个TCP过滤器,要么自己写一个内核驱动,要么使用libpcap等基于传统BPF的库,而传统BPF只是为以下场景设计的虚拟机数据包过滤,很难定制和扩展。在这样的背景下,eBPF应运而生。eBPF引入了JIT和寄存器,进一步扩展了BPF的功能。这背后的意思是,我们有了一个安全的、高性能的、基于事件的、支持JIT的字节码虚拟机!这实际上大大降低了扩展内核能力的门槛。我们不必担心在驱动程序中写入异常导致内核崩溃。我们也可以直接将clangforllvm编译成eBPF对象。社区也有基于bcc的一套Python实用工具。是的,性能监控和防火墙确实是目前eBPF的王牌场景,但我大胆预测,未来会不止于此,正如BrendanGregg最近在博客中喊出的口号:BPF是一种新型软件.也许在不久的将来,eBPF社区会产生更多有趣的东西,例如,我们可以使用eBPF来制作一个超高性能的Web服务器吗?可以做CDN加速器吗?BPF能否用来重新定义操作系统的进程调度?我喜欢eBPF的另一个重要原因是,内核应用开发者第一次可以忽略内核的类型和版本,只要内核能运行eBPF字节码,真正编译一次就完成了,每个内核都运行。所以有BPF在吃Linux的说法,不无道理。PingCAP也长期悄悄投入BPF社区,我们也开源了自己做的一些bcc工具。有关详细信息,请参阅pingcap/kdt存储库。值得一提的是,我们的一个bcc工具drsnoop被收录在了BrendanGregg的新书中,也算是对社区的一个小小的贡献。上面讨论的许多事情都是特定的技术。技术的落地离不开部署和运维。分布式系统的特点决定了其维护的复杂度远大于单机系统。在这种背景下,我认为解决方案可能是:不可变的基础设施。云和容器的流行使基础架构即代码的概念成为现实,使用描述性语言创建可重复的部署体验。这样可复用的描述其实很方便在开源社区分享,而且由于这些描述几乎完全相同,与具体的云实现无关,非常适合跨云部署和混合部署的场景数据中心部署。一些部署工具甚至诞生了自己的生态系统,比如Terraform/Chef/Ansible。有一种说法现在的运维工程师都是yaml语言工程师,其实很有道理:人总是会犯错的,传统的基于shell脚本的运维部署受环境影响太大,shell是自然不是很严谨的语言。描述意图并让机器做事是扩展的正确方法。4、作者简介黄东旭:分布式系统专家、架构师、开源软件作者。PingCAP联合创始人兼CTO,知名开源项目Codis/TiDB/TiKV的主要作者,曾就职于微软亚洲研究院、网易有道、Peapod。2015年创业,成立PingCAP,致力于下一代开源分布式数据库的研发,擅长分布式存储系统设计与实现,高并发后端架构设计。