架构漫谈

2019/10/15      2567 文章来源:优百 丨 作者:杨浩东

【引言】

“架构”一词由来已久,最早用于建筑学,原本指的是建筑物设计和建造的艺术。

在软件工程领域,软件架构也不是一个新名词,所谓“架构”,就是指软件系统的整体结构,包括软件的各个子模块以及模块之间关系的体现。软件架构和软件设计在概念上是统一的,二者没有区别,它们的产出都包括系统架构图、概要设计、详细设计等等,这些都体现出了架构师对于业务功能的理解和抽象,以及相对应的软件系统的设计。类似建筑设计师设计使用的图纸一样,架构图以及相关的文档实际上包含了软件系统的所有底层设计细节,这些细节信息共同支撑了顶层的设计实现,底层与顶层的设计都体现出软件系统的标准,发展方向和指导思想。

现实中我们经常会遇到为了加快发布速度而被匆忙搭建起来的系统。这类系统通常没有经过良好的设计便匆匆开工。初期,团队的开发效率都很高,然而随着产品的迭代,项目规模的扩大,不可避免的出现代码随处拷贝,复杂性扩散,代码质量下降,业务模块相互耦合等情况,工程师的开发效率呈直线下降的趋势,最终造成产品维护困难,甚至不可维护,投入成本成指数增长但是产品质量却在下降。问题所在就是大家对架构设计和代码质量的可维护性存在着长期、持续的忽视。

那么,实现一个好的系统架构的目标是什么呢?架构师们所做的各种决策,最终的目标就是为了能够达到,用最少的人力成本来满足构建和维护该系统的需求。判断一个软件系统架构优劣的标准很简单,就用它满足客户需求所需要的成本来判别。如果该系统成本很低,并且在整个后续的迭代过程中,包括需求的变更和维护等都维持一个相对低的成本,那么就可以说这种软件系统架构是一个优秀的软件架构设计。

【演化历程】

一般的互联网或者企业级的产品应用都是通过浏览器的web系统提供一组业务服务。

这类系统包括提供给用户可操作的、运行于浏览器环境中的具有良好UI样式的业务逻辑展示单元和输入单元,以及包括运行于服务器环境中、用各种面向对象语言构建的业务逻辑处理单元,和用于存储业务数据的各种关系型和非关系型数据存储单元。

常见互联网架构                                                                   服务化互联网架构

随着时代的发展,软件系统架构设计的表现和相关的部署风格等一直在不断演进。从最初的的单体架构逐步进化到分布式架构,目前分布式架构在各个软件系统中普遍存在,应用很广泛。

单体架构指的是整个系统的所有功能单元,完全部署到同一个服务器的同一个进程中。而分布式架构指的是功能单元分散到不同服务器的不同进程中,然后由多个进程共同来提供一组业务逻辑,又可细分为:面向服务架构(SOA)、分布式服务架构、微服务架构。其中,面向服务架构关注的是服务,即服务是最基本的业务功能单元,通过将业务系统服务化,可以将不同的业务模块解耦合,各种异构的系统之间可以实现服务的消费,资源的共享;而微服务架构则是相比SOA更细致化的架构服务,它是以实现一组微服务的方式来开发一个独立的应用系统的方法,其中,每个小微服务都运行在自己的进程中,通过全自动化的部署方式来进行独立部署,实现各个异构的系统之间服务的消费和资源的共享。微服务是将 SOA 中原本可能聚合在同一个系统内的多个服务组件拆分到各自独立的系统进程中,提供组件化的和可高度复用的微服务。微服务的优势在于:彻底的组件化,将一个服务中设计的多个微服务进行解耦合,各个微服务系统的规模小很多;每个微服务对应一个独立的开发和维护团队,有利于团队间独立的开发;各个微服务系统相互独立,仅通过rpc进行远程调用,可以实现独立部署和扩展,当系统性能出现瓶颈时,可以做到细颗粒度的有针对性的扩展和优化单个或者部分的微服务系统。同样的,微服务架构的缺点也很明显,微服务的拆分提高了对部署和测试的要求,部署和测试的复杂性大大提升;系统问题的排查、数据的一致性、系统监控等都会因为微服务的拆分而增加难度等等。总的来说,我们需要根据项目的应用环境,功能的复杂程度,团队结构的划分等来合理的采用不同的系统架构,而不是一味的使用最新或者最流行的系统架构。

【应用标准】

软件架构的实质就是规划如何将系统切分成组件,并整理好组件之间的排列关系,以及组件之间相互关联的方法。而设计系统架构的目的也是为了在工作中更好的对这些组件进行独立的开发、部署、运行以及维护。

要想构建一个好的软件系统,良好的架构设计和优秀的代码质量是必不可少的,按照SOLID原则来进行设计便可以帮助我们来解决这些问题。SOLID原则指导我们怎样去组织和封装提供服务的代码,使得软件易于维护、代码易于理解、组件易于复用。

SOLID原则包含如下:单一职责原则(SRP),开闭原则(OCP),里氏替换原则(LSP),接口隔离原则(ISP),依赖反转原则(DIP)

单一职责原则:任何一个软件模块都应该只对某一类行为者负责。具体来讲,就是把不同的业务功能进行隔离,确保一个业务系统的改动不会引起相关业务系统的改变和重新部署。

开闭原则:计算机软件系统应该易于扩展,但同时抗拒修改。意思是说一个设计良好的软件系统应该可以在不修改源代码的基础上就可以扩展功能。

里氏替换原则:如果当衍生类可以替换父类时,而软件的功能不受影响,那么子类对于父类具有可替换性。一旦违背了里氏替换原则,我们为此就不得不引入大量的冗余且复杂的功能代码。

接口隔离原则:任何层次的软件设计都要保持简洁,确保不会依赖不需要的东西,否则就会带来不必要的麻烦。

依赖反转原则:一个良好设计的系统,在源代码层面的依赖关系中需要多引用抽象类型,而非具体实现。因为抽象层是稳定的,我们会经常修改接口的具体实现,而很少去修改对应的抽象接口,那么当我们修改具体实现时,就不会影响对应的接口和相应的服务调用方,实现异构系统的独立性。在架构层面,是说各个系统之间需要组成有向无环图,确保系统之间不会出现相互依赖。

以上SOLID原则虽然是说具体代码层面的,但是对于系统架构设计层面的也有相应的指导思想,这里我们只需理解其背后想表达的理念并加以灵活运用,而不必纠结于名称或者是具体适用范围。

【结束语】

近年来,业界又提出了无服务器架构,即serverless架构。它是这样描述的,无服务器架构是基于互联网的系统,其中应用开发不使用常规的服务进程。而是将服务托管于例如亚马逊的Lamda服务等第三方服务。

Serverless架构也是一种微服务的架构,只不过它可以提供更碎片化的软件架构模式,即FaaS(Function as a Service)FaaS是基于函数的编程,它是相比于微服务更加细小的程序单元,我们可以针对一个函数来进行单独的扩展和优化。Serverless在降低运营成本,提升扩展能力等方面具有很大的优势。

可以发现,在系统架构的演进过程中,我们不断的将功能拆分为更加细颗粒度的、可以单独部署和扩展的异构系统。但是,采用什么样的架构,是需要根据项目和人员的具体情况来决定的,并且在项目的迭代工程中进行评估和调整的,最后选择一个适合的系统架构而切忌盲目跟风。