美文网首页DDIA
可靠,可扩展,可维护的应用--可维护性及概要

可靠,可扩展,可维护的应用--可维护性及概要

作者: 珊瑚海的世界 | 来源:发表于2018-03-10 22:47 被阅读0次

    可维护性

            众所周知,软件的大部分成本并不是处于其最初的开发阶段,而是在其持续的维护修复漏洞,保持其系统运行,调查故障,将其适应新平台,修改新用例,付偿技术成本和增加新功能。

            然而,不幸的是,许多从事软件系统工作的人不喜欢维护所谓的遗留系统 - 可能涉及修复其他人的错误,或者使用现在已经过时的平台,或者被迫做了他们从未打算过的系统。 每一个遗留系统都具有自身特点的不足,所以很难给出处理它们的一般建议。

            但是,我们在设计软件的时候,应考虑到在维护期间尽可能减少痛点,从而避免自己创建遗留系统。 为此,我们将特别关注软件系统的三个设计原则:

    可操作性

    让操作团队能够轻松地保持系统顺畅运行。

    简单

    通过从系统中移除尽可能多的复杂性,使新工程师能够轻松理解系统。 (注意这与用户界面的简单性不一样。)

    可演化

    使工程师能够轻松地对将来的系统进行更改,并根据需求的变化对其进行调整以适应意外的使用情况。 也称为可扩展性,可修改性或可塑性。

            正如以前的可靠性和可扩展性一样,实现这些目标并没有简单的解决方案。 相反,我们会考虑可操作性,简单性和可演化性的系统。

    可操作性:易于操作

            有人认为,“良好的操作通常可以解决坏的(或不完整的)软件的局限性,但不良的操作无法使软件可靠地运行”。 尽管操作的某些方面可以而且应该是自动化的,但首先要确保自动化的正常工作仍然取决于人类。

            运营团队对于保持软件系统平稳运行至关重要。 一个优秀的运营团队通常负责以下事宜:

    监控系统的运行状况,并在服务状态不佳时迅速恢复服务

    追踪问题的原因,例如系统故障或性能下降

    确保软件和平台保持最新,包括安全补丁

    了解不同系统如何相互影响,以便在造成损害之前避免有问题的更改

    预测未来的问题并在问题发生之前予以解决(例如,容量规划)

    为部署,配置管理等建立良好的实践和工具

    执行复杂的维护任务,例如将应用程序从一个平台移动到另一个平台

    随着配置更改而进行维护系统的安全性

    定义使操作可预测并有助于保持生产环境稳定的流程

    保持组织对系统的了解,即使是个人也是如此

           良好的可操作性意味着简化日常工作,使运营团队能够专注于高价值活动。 数据系统可以做各种事情来简化日常任务,包括:

    提供对系统运行时行为和内部的可视性,并提供良好的监控

    为自动化和与标准工具的集成提供良好的支持

    避免依赖个别机器(在系统整体继续不间断运行时允许机器停机维护)

    提供良好的文档和易于理解的操作模型(“如果我做X,Y会发生”)

    提供良好的默认行为,但也可以让管理员在需要时自由覆盖默认值

    在适当的情况下进行自我修复,但也可以让管理员在需要时手动控制系统状态

    展现可预见的行为,最大限度地减少异常

    简单:管理复杂性

            小型软件项目可以有令人愉快的简单和富有表现力的代码,但随着项目越来越大,它们往往变得非常复杂,难以理解。 这种复杂性降低了每个需要在系统上工作的人员的效率,进一步增加了维护成本。 一个陷入复杂性的软件项目有时被描述为a big ball of mud

            复杂性有各种可能的症状:状态空间的爆炸,模块的紧密耦合,纠结的依赖关系,不一致的命名和术语,旨在解决性能问题的黑客攻击,解决其他问题的特殊框架等等。 关于这个话题已经被很多人所谈论了。

            当复杂性使维护变得困难时,预算和时间安排往往会过度。 在复杂的软件中,进行更改时引入错误的风险更大:当系统难以让开发人员理解和推理时,隐藏的假设,意想不到的后果和意外的交互更容易被忽略。 相反,降低复杂性大大提高了软件的可维护性,因此简单性应该是我们构建系统的关键目标。

            简化系统并不一定意味着减少其功能; 它也意味着消除意外的复杂性。 Moseley和Marks 将复杂性定义为偶然的,如果它不是软件解决问题的固有问题(如用户所见),而只是来自实现

            我们用来消除意外复杂性的最好工具之一是抽象。 在一个干净,简单易懂的外观背后,一个好的抽象可以隐藏大量的实现细节。 一个好的抽象也可以用于各种不同的应用程序。 这种重用不仅比多次重复实现类似的东西更高效,而且还进而产生更高质量的软件,因为抽象组件中的质量改进使所有使用它的应用程序都受益。

            例如,高级编程语言是隐藏机器代码,CPU寄存器和系统调用的抽象。 SQL是一种抽象,它隐藏了复杂的磁盘和内存数据结构,来自其他客户端的并发请求以及崩溃后的不一致性。 当然,在用高级语言编程时,我们仍然使用机器码; 我们不直接使用它,因为编程语言抽象使我们不必考虑它。

            但是,找到好的抽象是非常困难的。 在分布式系统领域,虽然有许多好的算法,但我们不太清楚应该如何将它们打包到抽象中,以帮助我们将系统的复杂性保持在可管理的水平。

          在本书的整个过程中,我们将继续寻找良好的抽象,使我们能够将大型系统的一部分抽取为定义良好的可重用组件。

    可演化性:让改变变得容易

            你的系统的需求永远保持不变是极不可能的。 它们更有可能持续不断地变化:您学习新的知识,具有潜在危险的用例,业务优先级发生变化,用户请求新功能,新平台取代旧平台,法律或监管要求发生变化,系统的增长迫使架构发生变化等等。

            在组织流程方面,敏捷工作模式为适应变化提供了一个框架。 敏捷社区还开发了技术工具和模式,这些工具和模式在频繁变化的环境中开发软件时非常有用,如测试驱动开发(TDD)和重构。

            这些敏捷技术的大多数讨论都集中在相当小的本地规模(同一应用程序中的几个源代码文件)。 在本书中,我们将探索在更大数据系统层面提高灵活性的方法,可能由多个不同特性的应用程序或服务组成。 例如,你将如何“重构”Twitter的架构以便将方法1中的home timeline(第11页上的“描述负载”)从方法1重新组合到方法2?

            您可以轻松修改数据系统并使其适应不断变化的需求,这与其简单性和抽象性密切相关:简单易懂的系统通常比复杂系统更容易修改。 但是由于这是一个非常重要的想法,我们将用一个不同的词来指代数据系统层面的敏捷性:可演化性。

    概要

            在本章中,我们探讨了一些关于数据广泛应用的基本思路。 这些原则将指导我们完成本书的其余部分,后续我们将深入技术细节。

            应用程序必须满足各种要求才能有用。 有功能需求(应该做什么,例如允许以各种方式存储,检索,搜索和处理数据)以及一些非功能需求(一般属性,如安全性,可靠性,合规性,可扩展性,兼容性和可维护性)。 在本章中,我们详细讨论了可靠性,可扩展性和可维护性。

            可靠性意味着即使发生故障,也能使系统正常工作。 错误可以是硬件(通常是随机的和不相关的),软件(错误通常是系统的并且很难处理)以及人类(不可避免地会不时出错)。 容错技术可以隐藏最终用户的某些类型的故障。

            可扩展性意味着即使在负载增加的情况下也有保持性能良好的策略。 为了讨论可扩展性,我们首先需要定量描述负载和性能的方法。 我们简单地将Twitter的home timeline作为描述负载的示例,并将响应时间百分比作为衡量性能的一种方式。 在可扩展的系统中,您可以添加处理能力以在高负载下保持可靠。

            可维护性有许多方面,但实质上是为需要使用该系统的工程和运营团队提供更好的帮助。 良好的抽象可以帮助降低复杂性并使系统更易于修改和适应新的用例。良好的可操作性意味着对系统的健康有良好的可见性,并具有有效的管理方式。

            遗憾的是,让应用程序可靠,可扩展或可维护并不容易。 但是,某些模式和技术会不断出现在不同类型的应用程序中。 在接下来的几章中,我们将看看数据系统的一些例子,并分析它们如何实现这些目标。

            在本书后面的第三部分中,我们将看看由几个组件组成的系统的模式,比如图1-1中的组件。

    相关文章

      网友评论

        本文标题:可靠,可扩展,可维护的应用--可维护性及概要

        本文链接:https://www.haomeiwen.com/subject/xmtifftx.html