Fork me on GitHub

独立系统架构

微服务原则

Posted by Kaelzhang on August 30, 2019

独立系统架构

简介

独立系统架构(ISA,Independent Systems Architecture)是基于经验的最佳实践的集合,特别是微服务和自包含系统以及这些项目所面临的挑战。

通常采用微服务的项目都未能成功。 这套最佳实践可确保避免常见的陷阱,并实现微服务所承诺的优势。

但是,ISA原则并不总是适用 - 有关详细信息,请参阅常见问题

术语

这些原则中对于不能在系统中妥协且必须存在于系统中的方面使用“必须”。 “应该”用于具有很多好处的原则,但在某些情况下可以省略。 这里描述的原则谈论一个系统。 通常在企业的IT环境中会包含许多系统。,每个系统可能使用不同的原则构建,甚至可能采用完全不同的方法。

原则

原则一:模块

模块是一个存在已久的概念,一个系统由多个模块构成。

系统必须分为提供接口模块。 只能通过这些接口访问其他模块。 因此,模块不能直接依赖于其他模块的实现细节,例如:数据库中的内部数据表示。 其余原则定义了如何实现模块,以及ISA与其他模块化方法有何不同。

长期以来模块化被认为是处理大型复杂软件系统的重要工具。 使用术语“模块”重用了这些想法。 模块意味着例如:高凝聚力和低耦合作为架构的目标,或单一责任原则。 信息隐藏也意味着任何其他模块都不得访问数据和数据库。 因此,没有必要明确说明这些想法。

原则二:宏架构和微架构(The Micro Architecture)

系统必须具有两个明确分离的架构决策级别:

  • 宏架构包含涵盖所有模块的决策。 所有进一步的原则都是宏架构的一部分。
  • 微架构考虑可以针对每个模块单独进行的决策。

这里提出的架构允许大量自由。 但是,所有模块仍然需要显示为一个整体。 因此需要在宏架构层面上做出一些决策。 一经定义,宏和微架构清楚地说明了在哪个级别上必须决定什么。 目标是在宏架构级别上尽可能少地定义,以便在没有充分理由的情况下不受限制。 并非每个细节都应在宏架构中定义。 此外,宏架构应该专注于从长远来看相当稳定的决策,而微架构决策则不那么稳定。 宏架构影响所有模块,因此更难改变。 所以不应该过于频繁地改变它。

原则三:容器

模块必须作为单独的进程,容器或虚拟机实现,以最大限度地提高独立性并实现宏架构和微架构之间的分离。

将模块分成进程,容器或虚拟机允许如每个模块在不同平台上以不同的编程语言实现。 因此,技术决策仅针对一个模块。 此外,这种分离意味着每个模块都可以在没有任何其他模块崩溃的情况下崩溃。 如果所有模块只是一个过程的一部分,那么这将是不同的。 这有助于弹性能力。

原则四:通信集成

必须对系统的集成通信选项的选择进行限制和标准化。 可以使用同步或异步通信,并且/或者在UI级别上进行集成。 通信必须使用一组有限的协议,如:RESTful HTTP或消息传递。 为每个集成选项使用一个协议可能是有意义的。

模块被划分为多个进程。因此无法使用本地方法调用集成它们,但需要不同的集成方法。 标准意味着创建真正的系统。如果每个模块的集成方式均不相同,则很难将集成结果视为一个系统。 乍看似乎只有一种融合方式就足够了。但事实上,集成通常会在UI层和逻辑层上完成。这已经需要两种不同类型的集成。在同一系统中可能存在不同的情况,例如,同步和异步集成可能很有用。通信定义了模块用于交互的底层协议。当然,通信和集成之间存在关联。但是例如REST允许同步和异步集成。与集成一样,一种通信选择可能还不够。对于通信和集成,原则仅考虑系统内模块之间的通信。与其他系统的通信可以使用一组不同的集成和通信技术来完成。有时,通信和集成已经定义,因此系统无法更改。系统的公共接口也不同于架构的观点:更难于更改,因为更改将影响其他系统。

原则五:身份认证&元数据

元数据,例如 对于身份认证,必须标准化。 否则,用户需要登录每个微服务。 这可以使用例如:与每个调用/请求一起传输的令牌。 其他示例可能包括跟踪调用的跟踪ID及其通过微服务的相关调用。

用户不必登录每个模块,而是登录到整个系统。因此,传输身份验证信息(包括主体及其角色)也是标准化的一部分。授权与领域逻辑密切相关,应该在每个模块中完成。因此,每个模块都可以允许访问或特定操作。除认证信息之外的其他元数据也可能需要标准化。例如,跟踪微服务之间的调用,必须传输调用和所有相关调用的唯一ID。

原则六:独立的持续交付流水线

每个模块必须有自己独立的持续交付流水线。 测试是持续交付流水线的一部分,因此模块必须独立测试。

只有每个模块都可以自行部署,才能实现真正的独立性。架构只是一个先决条件。换句话说:如果架构允许独立模块,但它们仍然需要作为一个整体进行部署,那么该方法仅提供所需独立性的一部分,但仍然需要花费大量精力。在某些情况下,存在共享集成测试阶段。每个模块最终传播到此阶段并进行独立测试,即所有其他模块必须等到该模块通过集成测试阶段。这是部署流水线中的依赖性瓶颈的示例:在模块通过阶段之前,其他流水线无法继续。必须避免这种情况,例如通过使用消费者驱动的契约测试和通过Mock来测试模块之间的接口,或通过分离集成测试阶段。

原则七:标准化运维

运营应该标准化。 这包括配置,部署,日志分析,跟踪,监控和告警。 如果模块有非常具体的要求,标准可能会有例外。

每个模块都是一个单独的进程、容器或虚拟机。运维部门必须处理每一项问题,因此面临着巨大的挑战。标准化有助于应对这种复杂性。但是,可能仍然存在具有特殊要求的服务,这些服务可能使用不同的操作方法。另外:在“You build it - you run it”组织中,每个团队都应该负责选择最适合它们的操作方法。大多数情况下,这仍然是一种标准化方法,因为这会减少团队的工作量。请注意,该标准仅涵盖该技术。当然,每个模块可能都有自己的一组指标,告警等。ISA需要高度成熟的运维:大多数运维程序必须自动化。必须处理许多模块。缺乏这种成熟度可能会导致无法成功实施ISA。

原则八:标准化

应在接口级别强制执行运维,集成或通信的标准化。 例如,通信协议和数据结构可以标准化为使用HTTP交互的特定JSON有效载荷格式,但每个模块应该可以自由使用不同的REST库/实现。

在某种程度上,这是模块化的结果:模块可能只能通过接口访问。 对于任何标准案例理应如此, 例如:运维。 此外,技术水平的标准限制了技术的自由选择,这是该架构的主要优点。 但在某些情况下,可能无法将标准限制为接口级别。 所以该原则只是“应该”。

原则九:弹性

模块必须具有弹性

  • 它们必须对不可用的模块或通信问题进行补偿。
  • 它们必须能够应对意外停机而不会丢失数据或状态。
  • 必须可以将它们移动到其他运行时环境(主机,网络,配置等)。

模块级别的弹性极大地有助于整个分布式系统的高可用性的获得。 调度程序也可以选择重新启动模块或将它们移动到其他服务器。 模块必须能够处理这个问题。

其他原则

ISA(独立系统架构)是最佳实践的集合。 但是ISA没有定义完整的体系结构。 以下内容介绍了不属于ISA的其他原则以及它们被忽略的原因。

ISA定义了模块技术层面的内容。但系统如何拆分为模块超出ISA的范围。 领域驱动设计限界上下文是很好的指导原则。 但有时技术模块需要因为可扩展性等原因的分离也很重要。 正确拆分为模块非常困难,因此不能轻易地将其放在一些原则中。

架构可以产生巨大的组织和文化影响。 该方法允许更好的分离模块,允许独立,自组织的团队。 康威定律指出,软件架构反映了团队中的社会边界,因此组织与架构之间存在着密切的关系。 但是,ISA在不调整组织结构的场景下工作,因此这种想法可以通过这种方式更广泛地应用。

ISA不偏好通信协议或运维技术。 它陈述了一般原则,而不是具体的技术决策。

遵循这些原则可提供独立可扩展性,负载平衡和高可用性等优势。 然而,这些好处是遵循原则的结果而非原则本身,所以它们未被明确提及。

这些原则带来了不一致的数据等问题。 这些是分布式系统的基本挑战,需要加以解决。 这超出了ISA的定义。

参考资料

  • https://isa-principles.org/index.html

  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!