在软件架构领域中,流行将架构特征的范围置于系统级别。例如,当架构师谈论可伸缩性时,他们通常会围绕整个系统的可伸缩性进行讨论。这是十年前的假设,当时几乎所有系统都是单块的。随着现代工程技术及其支持的架构样式(例如微服务)的出现,架构特征的范围已大大缩小。这是随着软件开发生态系统持续不断发展而逐渐过时的一个典型例子。
在《构建演化架构》一书的撰写过程中,作者需要一种技术来衡量特定架构风格的结构性演变。现有措施均未提供正确的详细程度。在“结构性度量”中,我们讨论了各种代码级度量,这些度量使工程师可以分析架构的各个方面。但是,所有这些度量标准仅揭示了有关代码的底层细节,无法评估仍影响许多架构特性(尤其是运维特性)的代码库之外的依赖组件(例如数据库)。例如,无论架构师在设计高性能或弹性代码库上投入多少精力,如果系统使用的数据库与这些特征都不匹配,那么该应用将不会成功。
在评估许多运维架构特征时,架构师必须考虑代码库之外的会影响这些特征的相关组件。因此,架构师需要另一种方法来测量这些依赖性。这导致构建演化架构的作者定义了术语“架构量子”。要了解架构的量子定义,我们必须在这里预览一个关键指标,即共生。
耦合与共生
许多代码级耦合度量,例如传入和传出耦合(在“结构性度量”中进行了描述),都在太细粒度的级别上揭示了细节,无法进行架构分析。 1996年,Meilir Page-Jones出版了一本书,题为《每个程序员都应该了解面向对象设计》(Dorset House),其中包括他称为共生的几种新的耦合度量,其定义如下:
共生
如果一个组件的变更需要修改另一个组件以保持系统的整体正确性,则两个组件是共生的。
他定义了两种类型的共生:静态(可通过静态代码分析发现)和动态(涉及运行时行为)。为了定义架构量子,我们需要一种度量组件如何“共生”在一起的方法,这与共生概念相对应。例如,如果微服务架构中的两个服务共享某个类的相同类定义(例如地址),那么我们说它们在静态上是相互关联的—更改共享类需要同时更改两个服务。
对于动态共生,我们定义两种类型:同步和异步。两个分布式服务之间的同步呼叫使呼叫者等待被呼叫者的响应。另一方面,异步调用在事件驱动的架构中允许即忘的语义,从而允许两种不同的服务在操作架构中有所不同
架构量子和粒度
组件级耦合并不是将软件绑定在一起的唯一方法。许多业务概念在语义上将系统的各个部分绑定在一起,从而产生功能上的内聚。为了成功地设计、分析和开发软件,开发人员必须考虑所有可能破坏的耦合点。
许多具有科学知识的开发人员都从物理学中了解量子的概念,即相互作用中涉及的任何物理实体的最小量。 “量子”一词源自拉丁语,意思是“多大”或“多少”。我们采用了这个概念来定义架构量子:
架构量子
具有很高功能内聚和同步共生的可独立部署的工件。
此定义包含几个部分,在这里进行了剖析:
可独立部署
一个架构范围包括所有必需的组件,以独立于架构的其他部分起作用。例如,如果应用使用数据库,则它是重要的一部分,因为没有它,系统将无法运行。这一需求意味着,实际上,按照定义,使用单个数据库部署的所有旧系统都构成一个整体。但是,在微服务架构样式中,每个服务都包含自己的数据库(微服务中有限上下文驱动哲学的一部分),从而在该架构内创建多个量子。
高功能内聚
组件设计中的内聚性是指所包含的代码在目的上的统一程度。例如,具有与客户实体有关的属性和方法的客户组件表现出很高的内聚;而带有杂项方法随机集合的Utility组件则不会。
高功能内聚意味着架构量子可以做一些有目的的事情。在具有单个数据库的传统单块应用中,这种区别无关紧要。但是,在微服务架构中,开发人员通常会设计每种服务以匹配单个工作流(如"域驱动设计的有界上下文"中所述的有界上下文),因此表现出很高的功能内聚。
同步共生
同步共生意味着在应用上下文内或形成此架构范围的分布式服务之间进行同步调用。例如,如果微服务架构中的一项服务同步调用另一项服务,则每种服务在操作架构特征上都不会表现出极大的差异。如果呼叫者比被呼叫者具有更大的可伸缩性,则会发生超时和其他可靠性问题。因此,同步呼叫会在整个呼叫过程中产生动态连续性—如果一个呼叫正在等待另一个呼叫,则它们的操作架构特征在呼叫持续时间内必须相同。
我们定义了传统耦合指标和共生之间的关系,其中不包括我们新的沟通共生度量。我们在图中更新此图。
再举一个例子,考虑一个带有支付服务和拍卖服务的微服务架构。 拍卖结束时,拍卖服务会将付款信息发送到付款服务。 但是,假设付款服务只能每500毫秒处理一次付款,一次大量拍卖结束后会发生什么情况? 设计不良的架构将使第一个呼叫继续进行,并使其他呼叫超时。 或者,架构师可以设计“付款”和“拍卖”之间的异步通信链接,从而允许消息队列临时缓冲差异。 在这种情况下,异步共生将创建更灵活的架构。
架构量子概念为架构特性提供了新的范围。在现代系统中,架构师在量子级别而不是系统级别定义架构特征。通过将范围缩小到重要的操作问题,架构师可以及早发现架构难题,从而导致混合架构。为了说明架构量子度量提供的作用域,请考虑另一种架构选项Going, Going, Gone。
案例研究:Going, Going, Gone
我们介绍了架构Kata(势)的概念。考虑这一点,涉及在线拍卖公司。这是架构Kata的描述:
描述
一家拍卖公司希望将其网上拍卖扩大到全国范围。客户选择参加拍卖,等到拍卖开始,然后像拍卖师在房间里一样竞标。
用户数
每次拍卖最多可扩展至数百名参与者,可能最多可扩展至数千名参与者,并尽可能多地同时拍卖。
需求
- 拍卖必须尽可能实时。
- 投标人用信用卡注册;如果中标者,系统会自动从卡中扣款。
- 必须通过信誉指数来跟踪参与者。
- 竞价者可以观看拍卖的实时视频流以及所有竞价。
- 在线投标和实时投标都必须按照其放置顺序进行接收。
额外的上下文
- 拍卖公司正在通过与较小的竞争对手合并来积极扩张。
- 预算不受限制。这是一个战略方向。
- 公司刚退出诉讼,就指控欺诈的诉讼达成和解。
就像在“案例研究:硅谷三明治”中一样,架构师必须考虑以下所有需求才能确定架构特征:
“全国范围的拍卖”,“每次拍卖最多可扩展至数百名参与者,潜在地最多可扩展至数千名参与者,并尽可能多地同时拍卖”,“拍卖必须尽可能实时。”
这些需求中的每一个都暗示了支持大量用户的可伸缩性和支持拍卖的突发性的弹性。当需求明确要求可伸缩性时,弹性表示基于问题域的隐式特征。在考虑拍卖时,是否所有用户都在招标过程中有规律地访问,还是在接近尾声时变得更加频繁?领域知识对于架构师了解隐式架构特征至关重要。考虑到拍卖的实时性,架构师当然会认为性能是关键的架构特征。
“投标人用信用卡注册;如果竞标者中标,系统会自动向该卡收费。
这两个需求都明确指出安全性是一种架构特征。安全性实际上是每个应用中的隐式架构特征。因此,架构师依赖于架构特征定义的第二部分,它们影响了设计的某些结构方面。架构师应该设计一些特殊的东西来适应安全性,还是一般的设计和编码安全就足够了?架构师开发了通过设计安全处理信用卡的技术,而不必构建特殊的结构。例如,只要开发人员确保不要以纯文本形式存储信用卡号,在传输过程中进行加密等,那么架构师就不必针对安全性进行特殊考虑。
但是,第二个短语应使架构师停顿并要求进一步澄清。显然,安全性(欺诈)的某些方面过去是一个问题,因此,无论他们设计何种安全性级别,架构师都应要求进一步的投入。
“必须通过信誉指数来跟踪参与者。”
该需求提出了一些奇特的名称,例如"反拖拽",但该需求的跟踪部分可能提出了一些架构特征,例如可审计性和可登录性。决定因素又回到了定义的特征——这是否超出了问题领域的范围?架构师必须记住,产生架构特征的分析仅代表设计和实现应用的全部工作的一小部分—许多设计工作在此阶段之后进行!在架构定义的这一部分中,架构师会寻找具有结构影响的需求,而这些影响尚未被域涵盖。
架构师在确定领域与架构特征之间的关系时,有用的试纸测试方法是:需要实施领域知识还是抽象的架构特征?在《 Going, Going, Gone Kata》中,一位架构师在遇到“信誉指数”一词时会寻求业务分析师或其他主题专家来解释他们的想法。换句话说,“信誉指数”一词不是标准定义,而是更常见的架构特征。作为反例,当架构师讨论弹性(处理用户突发事件的能力)时,他们可以纯粹抽象地讨论架构特征—他们考虑使用哪种应用无关紧要:银行业务、目录站点、流视频等等。架构师必须确定需求是否尚未被领域所涵盖,并需要特定的结构,从而提高了对结构特征的考虑。
“拍卖公司正在通过与较小的竞争对手合并来积极扩张。”
尽管此需求可能不会对应用设计产生直接影响,但它可能成为在多个选项之间进行权衡的决定因素。例如,架构师必须经常选择诸如集成架构的通信协议之类的细节:如果与新合并的公司的集成不是问题,那么架构师就可以选择针对该问题的高度特定的东西。另一方面,架构师可能会选择一些不完美的东西来适应一些其他的权衡,例如互操作性。微妙的隐式架构特征(例如这种普遍存在的架构)说明了为什么做好这项工作会带来挑战。
“预算不受限制。这是一个战略方向。”
一些架构选项对解决方案施加预算限制,以代表常见的现实世界的权衡。但是,在Going, Going, Gone Kata中却没有。这使架构师可以选择更精细和/或特殊用途的架构,这对未来的需求将是有益的。
“竞标者可以观看拍卖的实时视频流,并可以实时查看所有竞标。”“在线竞标和实时竞标都必须按照其放置顺序进行。”
此需求提出了一个有趣的架构挑战,肯定会影响应用的结构,并暴露了将架构特征视为系统范围评估的徒劳。考虑可用性—在整个架构中是否需要统一的?换句话说,一个竞标者的可用性是否比数百个竞标者之一的可用性重要?显然,架构师希望为这两种方法都采取好的措施,但其中一项显然更为关键:如果拍卖师无法访问该网站,则任何人都无法进行在线竞标。可靠性通常与可用性一起出现。它解决了运行方面的问题,例如正常运行时间,数据完整性以及应用程序可靠性的其他度量。例如,在拍卖现场,架构师必须确保消息排序可靠、正确、消除了竞争状况和其他问题。
Going, Going, Gone Kata中的最后一项需求突出了在架构上比系统级别更细化的范围的需求。使用架构量子度量,架构师可以在量子级别上确定架构特征。例如,在《 Going, Going, Gone》中,架构师会注意到该架构的不同部分需要不同的特征:流式竞标,在线竞标和拍卖人是三个明显的选择。架构师使用架构量子度量作为一种思考部署,耦合,数据应驻留的位置以及架构内通信方式的方式。在此方法中,架构师可以分析每个架构量的不同架构特征,从而在此过程中更早地进行混合架构设计。
因此,对于Going, Going, Gone,我们确定了以下量子和相应的架构特征:
投标人反馈
包含出价的出价流和视频流
- 可用性
- 可扩展性
- 性能
拍卖人员
现场拍卖师
- 可用性
- 可靠性
- 可扩展性
- 弹性
- 性能
- 安全
投标人
网上竞标和竞标
- 可靠性
- 可用性
- 可扩展性
- 弹性