微服务治理与去中心化
产品并非项目
我们所能看到的大多数应用程序开发都使用一个项目模型:目标是交付软件,目的是交付一些软件,然后将其视为已完成。完成后,软件将移交给维护组织,构建它的项目团队将被解散。
微服务支持者倾向于避免这种模型,而是倾向于认为团队应该在其整个生命周期内拥有产品。对此的一个共同启示是亚马逊的概念“你构建,运行它”,开发团队对生产中的软件负全部责任。这使开发人员能够日常接触他们的软件在生产中的行为,并增加与用户的联系,因为他们必须承担至少一些支持负担。
产品心态,与业务能力的联系紧密相连。不是将软件视为一组要完成的功能,而是存在一种持续的关系,其中的问题是软件如何帮助其用户增强业务能力。
没有理由为什么这种方法不能与单一应用程序一起使用,但较小的服务粒度可以使创建服务开发人员与其用户之间的个人关系变得更加容易。
智能终端和哑管道
当构建不同进程之间的通信结构时,我们会看到许多产品和方法都强调将重要的智慧放入通信机制本身。一个很好的例子是企业服务总线(ESB),其中 ESB 产品通常包括用于消息路由,编排,转换和应用业务规则的复杂工具。
而微服务社区倾向于采用另一种方法:智能终端和哑管。从微服务构建的应用程序旨在尽可能地解耦和内聚 - 它们拥有自己的领域逻辑,看起来像传统、经典的 Unix 上的过滤器 - 接收请求,适当地应用逻辑并产生响应。这些是使用简单的 RESTish 协议而不是复杂的协议(如 WS-Choreography 或 BPEL 或中央工具的编排)编排的。
最常用的两种协议是 HTTP 请求 - 响应资源 API 和轻量级消息传递。第一个最好的表达方式是 web 的一部分,但没有隐藏在 web 后面。
微服务团队使用万维网(在很大程度上,Unix)构建的原则和协议。经常使用的资源可以通过开发人员或操作人员的非常小的努力来缓存。
常用的第二种方法是通过轻量级消息总线进行消息传递。选择的基础设施通常是愚蠢的(如同仅作为消息路由器那样愚蠢) - 像 RabbitMQ 或 ZeroMQ 这样的简单实现不仅仅提供可靠的异步结构 - 智能仍然存在于生成和消费消息;在服务中。
在一个单体应用当中,组件在进程中执行,它们之间的通信是通过方法调用或函数调用。将单体应用变为微服务的最大问题在于改变通信模式。从内存中方法调用到 RPC 的简单转换导致繁琐的通信,这些通信效果不佳。相反,您需要用粗粒度的方法替换细粒度的通信。
注意:跨进程的调用,一定要把接口定义的粗粒度,一次调用尽可能拿到所有需要的数据。相反,传统进程内的调用,越细越好。
去中心化的治理
中心化治理的后果之一是在单一技术平台上实现标准化的趋势。经验表明,这种方法是有限的 - 不是每个平台都是一样的,也不是每个解决方案都是一致的。我们推荐使用正确的工具来完成正确的工作,然而传统单体应用程序可以在一定程度上利用不同的语言,但这种做法并不常见。
将单体应用的组件划分成服务之后,我们在构建每个服务时都有选择。您想使用 node.js 来支持一个简单的报告页面吗?去争取它。C++ 用于一个特别接近实时的组件?好的。您想换一种更适合一个组件的读取行为的不同风格的数据库吗?我们有技术来重构他。
当然,仅仅因为你可以做某事,并不意味着你应该这么去做 - 但以这种方式对系统进行划分意味着你可以选择。
构建微服务的团队也喜欢使用不同的标准方法。与其使用一套写在纸上的已定义标准,他们更愿意开发出有用的工具,其他开发人员可以使用这些工具来解决与他们所面临的问题类似的问题。这些工具通常是从实现中获得的,并与更广泛的组共享,有时,但不是仅使用内部开放源代码模型。现在 Git 和 Github 已经成为事实上的版本控制系统的选择,开源实践在企业内部越来越普遍。
Netflix 是遵循这一理念的组织的一个很好的例子。共享有用的,最重要的是经过实战考验的代码,因为库鼓励其他开发人员以类似的方式解决类似问题,但如果需要,可以选择不同的方法。共享库往往侧重于数据存储,进程间通信的常见问题,我们将在下面进一步讨论基础架构自动化。
对于微服务社区来说,管理费用特别缺乏吸引力。这并不是说社区不重视服务合同。恰恰相反,因为往往会有更多。只是他们正在寻找管理这些合同的不同方式。像容忍阅读器和消费者驱动的合同这样的模式通常应用于微服务。这些援助服务合同独立发展。在构建过程中执行消费者驱动的合同可以增强信心,并提供有关您的服务是否正常运行的快速反馈。事实上,我们知道澳大利亚的一个团队通过消费者驱动的合同推动新服务的建设。他们使用简单的工具来定义服务合同。在编写新服务的代码之前,这将成为自动构建的一部分。然后,该服务仅在满足合同的情况下构建 - 这是在构建新软件时避免 'YAGNI' 困境的优雅方法。这些技术和围绕它们成长的工具通过减少服务之间的时间耦合来限制中央合同管理的需要。
也许分散治理的最高点是建立它/运行它由亚马逊推广的精神。团队负责他们构建的软件的所有方面,包括全天候运行软件。这种责任水平的下放绝对不是常态,但我们确实看到越来越多的公司将责任推向开发团队。Netflix 是另一个采用这种精神的组织。每天晚上凌晨 3 点被您的寻呼机唤醒,无疑是在编写代码时专注于质量的强大动力。这些想法与传统的集中治理模式相差甚远。
去中心化的数据管理
数据管理的去中心化以多种不同的方式呈现。在最抽象的层面上,它意味着世界的概念模型在不同系统之间会有所不同。在整合大型企业时,这是一个常见问题,客户的销售视角将与支持视角不同。在销售视角中称为客户的某些内容可能根本不会出现在支持视角中。那些做的可能具有不同的属性和(更糟糕的)具有微妙不同语义的共同属性。
此问题在应用程序之间很常见,但也可能在应用程序中发生,特别是在将应用程序划分为多个单独的组件时。一种有用的思考方式是有界上下文的领域驱动设计概念。DDD 将复杂域划分为多个有界上下文,并映射出它们之间的关系。此过程对单体应用和微服务体系结构都很有用,但服务和上下文边界之间存在自然关联,这有助于澄清,正如我们在业务功能部分中所述,强化了分离。
除了关于概念模型的分散决策之外,微服务还分散了数据存储决策。虽然单一应用程序更喜欢使用单个逻辑数据库来存储持久性数据,但企业通常更喜欢在一系列应用程序中使用单个数据库 - 其中许多决策是通过供应商围绕许可的商业模型来实现的。微服务更喜欢让每个服务管理自己的数据库,可以是同一数据库技术的不同实例,也可以是完全不同的数据库系统 - 这种方法称为 Polyglot Persistence。您可以在整体中使用多语言持久性,但它在微服务中更常出现。
基础设施自动化
基础设施自动化技术在过去几年中发生了巨大变化 - 特别是云和 AWS 的发展降低了构建,部署和运行微服务的操作复杂性。
许多使用微服务构建的产品或系统都是由具有丰富的持续交付经验的团队构建的,并且是前身的持续集成。以这种方式构建软件的团队广泛使用基础设施自动化技术。这在下面显示的构建管道中说明。
由于这不是关于持续交付的文章,我们将在这里引起注意几个关键功能。我们希望尽可能多的信心使我们的软件正常工作,因此我们进行了大量的自动化测试。推广工作软件“向上”管道意味着我们自动部署到每个新环境。
一个单体应用程序将在这些环境中非常随意地构建、测试和推送。事实证明,一旦您投资于自动化一个整体的生产路径,那么部署更多的应用程序就不再那么可怕了。记住,持续交付的目标之一是使部署变得简单,因此无论是它的一个或三个应用程序,只要它仍然简单,就不重要了。
我们看到团队使用广泛的基础设施自动化的另一个领域是管理生产中的微服务。与我们上面的断言相反,只要部署很简单,单体应用和微服务之间没有太大的区别,每个部署的运营环境可能会截然不同。
针对于失败来设计
使用服务作为组件的结果是,需要设计应用程序以便它们能够容忍服务的失败。由于供应商不可用,任何服务调用都可能失败,客户必须尽可能优雅地对此做出响应。与单体应用设计相比,这是微服务一个缺点,因为它引入了额外的复杂性来处理它。结果是微服务团队不断反思服务失败如何影响用户体验。Netflix 的 Simian Army 在工作日引发服务甚至数据中心的故障,以测试应用程序的弹性和监控。
这种生产中的自动化测试足以让大多数运维团队在休息一周之前就会发抖。这并不是说整体式建筑风格不具备复杂的监控设置 - 在我们的经验中它不常见。
由于服务可能随时发生故障,因此能够快速检测故障并在可能的情况下自动恢复服务非常重要。微服务应用程序非常重视应用程序的实时监控,检查架构元素(数据库每秒获得多少请求)和业务相关度量(例如每分钟收到多少订单)。语义监控可以提供出现问题的早期预警系统,从而触发开发团队跟进和调查。
注意:熔断器概念就是因为这个原因出来的,Spring Cloud Hystrix 的由来。
Last updated