美文网首页
第18章 选择合适的架构风格

第18章 选择合适的架构风格

作者: 城里的月光_欧阳 | 来源:发表于2021-01-21 21:50 被阅读0次

    视具体情况而定!当有了所有的选择(新的几乎每天都有),我们想告诉你使用哪一个,但我们不能。没有什么比一个组织中的一系列因素以及它构建的软件更相关的了。选择一种架构风格代表了对架构特性、领域思考、战略目标和一系列其他事情进行权衡的分析和思考的最终结果。

    无论决策的背景如何,在选择适当的架构风格方面存在一些通用性的建议。

    架构方面的“潮流”转向

    大家偏好的架构风格会随着时间的推移而变化,这是由许多因素驱动的:

    过去的观察

    新的架构风格通常来自于过去经验中的观察和痛点。架构师在过去对系统上的经验会影响他们对未来系统的想法。架构师必须依靠他们过去的经验,正是这种经验让这个人在一开始成为了一名架构师。通常,新的架构设计反映了过去架构风格的特定缺陷。例如,架构师在构建了具有代码重用特性的体系结构之后,认真地重新考虑了代码重用可能造成的影响,然后意识到了负面的权衡利害关系。

    生态系统的变化

    不断变化是软件开发生态系统的一个可靠特征-所有的东西都在不断变化。我们生态系统的变化尤其混乱,甚至连变化的类型都无法预测。例如,几年前,没有人知道Kubernetes是什么,但现在世界各地有多个研讨会并有数千名开发人员参与。再过几年,Kubernetes可能会被其他尚未编写的工具所取代。

    新的能力

    当新的能力出现时,架构可能不仅仅是用一种工具替换另一种工具,而是转向一种全新的范式。例如,很少有架构师或开发人员预料到Docker等容器的出现会引起软件开发领域的结构性变化。虽然这是一个进化的步骤,但它对架构师、工具、工程实践和许多其他因素的影响令业内人士感到震惊。生态系统的不断变化也定期提供新的工具和功能集合。架构师不仅要对新的工具,而且要对新的范式保持敏锐的眼光。有些东西可能只是看起来像我们已经拥有的东西中的一个新的事物,但它可能包括细微差别或其他变化,使它成为游戏规则的改变者。新的能力甚至不必撼动整个开发世界-新的特性可能只是与架构师的目标完全一致的微小变化。

    加速度

    不仅生态系统在不断变化,而且变化速率也在不断上升。新的工具产生新的工程实践,从而产生新的设计和功能。架构师生活在一个不断变化的状态中,因为变化是无处不在的,而且是不变的。

    领域变化

    开发人员为其编写软件的领域会不断地发生变化,要么是因为业务不断发展,要么是因为与其他公司合并等因素。

    技术变化

    随着技术的不断演进,组织试图跟上至少这些变化中的一部分,尤其是那些具有明显基本利益的变化。

    外部因素

    许多只与软件开发相关联的外部因素可能会驱动组织内部的变化。例如,架构师和开发人员可能对某个特定的工具非常满意,但是许可成本已经变得令人望而却步,迫使他们转移到另一个选项。

    无论一个组织在当前的架构潮流方面处于什么位置,架构师都应该了解当前的行业趋势,以便明智地决定何时遵循潮流和何时作出例外的选择。

    决策标准

    在选择一种架构风格时,架构师必须将对领域设计的结构有贡献的所有各种因素考虑进来。从根本上说,架构师设计两件事:到底指定的领域是什么,以及使系统成功所需的所有其他结构化元素。

    架构师在进行设计决策时,应考虑以下几点:

    领域

    架构师应该了解领域的许多重要方面,尤其是那些影响操作架构特性的方面。架构师不必是主题专家,但他们必须至少对设计领域的重要方面有一个良好的总体理解。

    影响结构的架构特性

    架构师必须发现并阐明支持领域和其他外部因素所需的架构特性。

    数据架构

    架构师和数据库管理员必须在数据库、模式和其他与数据相关的问题上进行协作。在本书中,我们没有涉及太多关于数据架构的内容;它有自身专门的研究。但是,架构师必须了解数据设计可能对其设计产生的影响,特别是当新系统必须与旧的和/或正在使用的数据架构交互时。

    组织因素

    许多外部因素可能会对设计造成影响。例如,特定云供应商的费用成本可能会妨碍理想的设计。或者该公司计划进行合并和收购,这鼓励架构师倾向于开放解决方案和集成架构。

    了解流程、团队和运营问题

    许多特定的项目因素会影响架构师的设计,例如软件开发过程、与操作的交互(或缺少),以及QA过程。例如,如果一个组织在敏捷工程实践方面不够成熟,那么依赖这些实践来获得成功的架构风格将带来困难。

    领域/架构同构

    一些问题域与架构的拓扑结构相匹配。例如,微内核架构风格非常适合需要可定制化的系统,架构师可以将定制化设计为插件。另一个例子可能是需要大量离散操作的基因组分析,而基于空间的架构则提供大量离散处理器。

    类似地,一些问题域可能特别不适合某些架构风格。例如,高度可扩展系统与大型单体设计相抗,因为架构师发现很难在高度耦合的代码库中支持大量并发用户。包含大量语义耦合的问题域与高度解耦的分布式架构很难匹配。例如,由多页表单组成的保险公司应用(每个表单都基于前几页的上下文)很难在微服务中建模。这是一个高度耦合的问题,在解耦的架构中会给架构师带来设计挑战;像基于服务的架构这种耦合较少的架构将更适合这个问题。

    考虑到所有这些因素,架构师必须做出几个决定:

    单体 vs 分布式

    使用前面讨论的量子概念,架构师必须确定一组架构特性是否足以满足设计,或者系统的不同部分是否需要不同的架构特性?单个集合意味着一个单体是合适的(尽管其他因素可能会促使架构师走向分布式架构),而不同的架构特性意味着需要一个分布式架构。

    数据应该存放在哪里?

    如果单体架构,则架构师通常假设有一个或几个关系数据库。在分布式架构中,架构师必须决定哪些服务应该持久化数据,这也意味着要考虑数据必须如何在整个架构中流动以构建工作流。架构师在设计时必须同时考虑结构和行为,不要害怕反复设计以找到更好的组合。

    服务之间的通信方式是同步的还是异步的?

    一旦架构师确定了数据分区,他们的下一个设计考虑是服务之间使用同步还是异步通信?同步通信在大多数情况下更方便,但它会带来可扩展性、可靠性和其他不需要的特性。异步通信可以在性能和扩展方面提供独特的好处,但会带来一系列令人头痛的问题:数据同步、死锁、竞争条件、调试等等。

    由于同步通信带来的设计、实现和调试挑战较少,架构师应该尽可能默认使用同步通信,只在必要时使用异步通信。

    提示

    默认情况下使用同步,必要时使用异步。

    这个设计过程的输出是架构拓扑,考虑到架构师选择了什么架构风格(和混合架构),架构决策记录了架构师花费最多精力的设计部分,而架构适配功能保护了重要的架构原则和可操作架构特性。

    单体架构案例研究:Silicon三明治

    在Silicon三明治架构案例中,在研究架构特性之后,我们确定单个量子足以实现这个系统。另外,这是一个简单的应用,没有庞大的预算,所以简单的单体架构具有吸引力。

    然而,我们为Silicon三明治创建了两种不同的组件设计:一种是按领域划分,另一种是按技术划分。考虑到解决方案的简单性,我们将为每个解决方案创建设计并涵盖利害权衡。

    模块化单体

    一个模块化的单体用单个数据库构建以领域为中心的组件,作为单个量子来部署;Silicon三明治的模块化单体设计如图18-1所示。

    这是一个具有单个关系数据库的单体,通过单个基于web的用户界面(对移动设备进行了仔细的设计考虑)实现,以降低总体成本。架构师先前识别的每个领域都显示为组件。如果时间和资源充足,架构师应该考虑创建与领域组件划分相同的表和其他数据库资产,允许此架构在未来需要时更容易地迁移到分布式架构上来。

    图18-1. Silicon三明治的模块化单体实现

    因为架构风格本身并不内在地处理定制化,所以架构师必须确保该特性成为领域设计的一部分。在这种情况下,架构师设计了一个Override端点,开发人员可以在该端点上传单独的定制化。相应地,架构师必须确保每个领域组件都为每个可定制特性引用Override组件,这将形成一个完美的适配功能。

    微内核

    架构师在Silicon三明治中确定的架构特性之一是可定制性。从领域/架构同构的角度来看,架构师可以选择使用微内核来实现它,如图18-2所示。

    图18-2.Silicon三明治的微内核实现

    在图18-2中,核心系统由领域组件和单个关系数据库组成。与前面的设计一样,领域和数据设计之间的仔细同步将允许将来将核心系统迁移到分布式架构。每个自定义项都出现在一个插件中,公共自定义项出现在一组插件中(带有一个相应的数据库),以及一系列本地自定义项,每个本地自定义项都有自己的数据。因为没有任何一个插件需要与其他插件耦合,所以它们可以各自维护它们的数据,从而使插件解耦。

    这里的另一个独特的设计元素利用了Backends for Frontends(BFF)模式,使API层成为一个薄的微内核适配器。它从后端提供通用信息,BFF适配器将通用信息转换为适合前端设备的格式。例如,iOS的BFF将从后端获取通用输出,并根据iOS本机应用的期望对其进行自定义:数据格式、分页、延迟和其他因素。构建每个BFF适配器允许最丰富的用户界面和扩展能力,以支持未来的其他设备,这是微内核风格的好处之一。

    Silicon三明治架构中任何部分的通信都可以是同步的,这种架构不需要极高的性能或弹性要求,而且任何操作都不会很冗长。

    分布式架构案例研究:Going,Going,Gone

    Going,Going,Gone(GGG)套路提出了更有趣的架构挑战。基于“案例研究:Going,Going,Gone:发现组件”中的组件分析,该架构需要针对架构的不同部分区分出不同的架构特性。例如,可用性和可扩展性等架构特性将在拍卖者和竞拍者等角色之间有所不同。

    GGG的需求还明确地说明了某些雄心勃勃的规模、弹性、性能级别,以及许多其他棘手的操作性架构特性。架构师需要选择一种允许在架构中的细粒度级别进行高度定制化的模式。在候选的分布式架构中,低级别的事件驱动或微服务架构与大多数架构特性相匹配。在这两者中,微服务更好地支持不同的操作架构特性,纯粹的事件驱动架构通常不会因为这些操作架构特性而将各个部分分开,而是基于通信风格是编制还是编排来进行划分。

    在微服务中,实现既定的性能将是一个挑战,但是架构师通常可以通过设计来适应架构的任何弱点。例如,虽然微服务天然地提供了高度的可扩展性,但架构师通常必须解决由过多的编制、过于激进的数据分离等引起的特定性能问题。

    使用微服务的GGG实现如图18-3所示。

    图18-3.Going,Going,Gone的微服务实现

    在图18-3中,每个标识的组件都成为架构中的服务,匹配组件和服务粒度。GGG有三个不同的用户界面:

    投标人

        网上拍卖的众多竞拍者。

    拍卖人

        每次拍卖有一个拍卖人。

    流式摄录机

        负责流式视频和投标流给投标人的服务。请注意,这是一个只读流,允许在需要更新时进行不可用的优化。

    以下服务出现在GGG架构的设计中:

    BidCapture

        捕获在线投标者条目并将其异步发送到投标跟踪器。这个服务不需要持久化,因为它充当了在线竞价的管道。

    BidStreamer

        以高性能、只读流的形式将投标反馈给在线参与者。

    BidTracker

        跟踪AuctioneerCapture和BidCapture的出价。这是一个将两个不同的信息流统一起来的组件,它尽可能接近实时地对投标进行排序。请注意,到该服务的两个入站连接都是异步的,允许开发人员使用消息队列作为缓冲区来处理速率差异很大的消息流。

    Auctioneer Capture

        捕获拍卖人的出价。“案例研究:Going,Going,Gone:发现组件”中的量子分析结果导致架构师将投标捕获和拍卖捕获分开,因为它们具有完全不同的架构特性。

    Auction Session

        这将管理单个拍卖的工作流。

    Payment

        在拍卖会话完成拍卖后处理支付信息的第三方支付提供商。

    Video Capture

        捕获现场拍卖的视频流。

    Video Streamer

        将拍卖视频流式传输给在线竞拍者。

    架构师很小心地确定了这个架构中的同步和异步通信风格。他们对异步通信的选择主要是通过适应服务之间不同的操作架构特性来驱动的。例如,如果支付服务只能每500毫秒处理一次新的支付,并且大量拍卖同时结束,那么服务之间的同步通信将导致超时和其他可靠性问题。通过使用消息队列,架构师可以为表现出脆弱性的架构的关键部分增加可靠性。

    在最后的分析中,这个设计分解为五个量子,如图18-4所示。

    图18-4.GGG的量子边界

    在图18-4中,设计包括了支付、拍卖人、投标人、投标人流和投标跟踪器大致对应的服务的量子。图中的容器堆栈表示多个实例。在组件设计阶段使用量子分析可以让架构师更容易地识别服务、数据和通信边界。

    请注意,这不是GGG的“正确”设计,当然也不是唯一的设计。我们甚至不认为这是最好的设计,但它似乎有一整套最不坏的利弊权衡。选择微服务,然后聪明地使用事件和消息,允许架构利用最通用的架构模式,同时为未来的开发和扩展奠定基础。


    原文参考:https://www.jianshu.com/p/3ba6ece4e21c

    全书翻译目录:https://www.jianshu.com/p/05711d172dfa

    相关文章

      网友评论

          本文标题:第18章 选择合适的架构风格

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