https://www.atlassian.com/continuous-delivery/microservices
什么是微服务?
术语“微服务”是一个现代术语,用于描述分布式、网络化项目中的传统“关注点分离”模式。微服务是一种遵循古老的unix基本哲学的思想,即“小而锋利的工具”。这两个概念都建立在另一个基本的计算机科学“组合”模式的基础上,这意味着复杂系统是较低层次的可组合实体的总和。
组合贯穿于软件项目的所有层。在最底层,即“单元级”,各个独立的代码函数通过共享接口相互交互,以创建代码的集合或“库”。在操作系统shell级别,可以组合shell命令来创建具有更高级别功能的管道。微服务是发生在Web服务之间的组合级别。微服务是负责一段域逻辑的web服务。微服务通过简单的网络协议(如REST)相互交互以完成操作,但是它们不知道其他服务在内部是如何工作的。微服务之间的这种和谐交互是一种微服务体系结构。
随着软件团队正在寻找改善发布工作流程的新方法,微服务架构(MSA)受到了广泛关注。 亚马逊,Netflix和Ebay都是公开接受这种软件构建方式的公司,它们通过发布自己的经验和开发可帮助他人采用的工具,为社区做出了贡献。
微服务的指导原则是通过将应用程序的业务组件划分为多个小服务来构建应用程序,这些小服务可以相互独立地部署和操作。
开发人员可以组成规模较小的团队,专门研究具有不同堆栈和解耦部署的不同服务。 关注点的分离和独立功能的分离使简化的敏捷软件开发实践得以实现,例如连续交付和集成。
面向服务的体系结构(SOA)与微服务
面向服务的体系结构和微服务是两种高级的web服务体系结构。微服务可以被看作是SOA的精简版。SOA有4种基本服务类型:业务、企业、应用程序和基础设施服务。这些类型定义了底层服务的相关领域特定职责。相比之下,微服务只有两种服务类型;功能和基础设施。
这两个架构在企业的不同层共享同一套标准。MSA的存在归结于SOA模式的成功。因此,MSA模式是SOA的一个子集。这里主要关注的是每个服务的运行时自治。
整体应用vs微服务
微服务将主要业务领域特定的关注点解耦为独立的代码库。可以将单一应用程序体系结构看作微服务的逆向。一个整体是一个代码库,它将所有的业务联系在一起。在项目生命周期的早期,为了简化代码管理、认知开销和部署,单体可以很方便。这使得整体中的所有东西都可以立即释放。
许多项目最初都是从Monolith开始的,然后发展成为微服务架构。 随着将新功能添加到Monolith上,让许多开发人员使用单一代码库可能变得很麻烦。 代码冲突变得更加频繁,并且对一项功能进行更新的风险在不相关的功能中引入了错误。 当出现这些不良模式时,可能是时候讨论向微服务迁移的问题了。
微服务架构如何运作
以一个假设的电子商务软件项目为例。有一些明确定义的特定于领域的业务特性。电子商务网站有一个用户登录、注销的认证系统。购物车,用于保存用户感兴趣的产品列表。计费系统允许用户为他们的购买付款。
在微服务体系结构中,这些示例业务域将是独立的服务。以计费系统为例。根据公司员工的数量,可能会有一个专门的“账单团队”,他们拥有这个账单微服务的开发和质量保证。计费微服务将有自己的发布时间表和部署剧本。账单服务将提供文档化和版本化的API,以便其他服务可以通信并利用其功能。
微服务的优缺点
优点:
水平扩展。微服务按设计进行分发,可以部署在集群中。这支持跨服务边界的动态水平扩展。如果微服务正在最大限度地提高其负载能力,则可以将该服务的新实例快速部署到相应的集群,以帮助缓解压力。
独立的团队执行。微服务所有权团队可以独立于组织中的其他功能团队进行操作。这允许更快速地执行和交付新功能。
更加关注质量。将业务关注点分离到独立的微服务中,可以确保拥有该服务的服务团队专注于完整的高质量交付。
缺点:
基础设施成本指数级增长。组织在其生产部署中添加的每个新微服务都有其自己的测试套件、部署剧本、托管基础设施、监控工具等成本。
增加组织的开销。需要增加通信和协作级别,以协调微服务体系结构团队之间的更新和接口。
开发环境的复杂性。当一个项目被分解为多个微服务时,它增加了在本地开发设置期间复制分布式体系结构的挑战。
微服务的未来
容器化和容器的部署,是分布式基础设施的一种新模式。Docker和Kubernetes等工具用于将服务打包成一个可以快速部署和丢弃的完整“容器”。这些新的基础设施工具是对微服务体系结构的补充。微服务可以使用容器管理系统进行容器化,并且易于部署和管理。
微服务的采用应该被视为一个过程,而不是团队的直接目标。从小事开始,了解分布式系统的技术需求,了解如何优雅地处理失败和扩展单个组件。然后,随着经验和知识的积累,您可以逐渐提取出越来越多的服务。
微服务体系结构仍然相当年轻,但它是开发应用程序的一种很有前途的方法,绝对值得研究,但请记住,它可能(还)不适合您的团队。
如何构建微服务
步骤1:从整体开始
微服务的第一个最佳实践是您可能不需要它们。如果您没有任何用户来申请应用程序,那么在您构建MVP时,业务需求将迅速变化。这仅仅是由于软件开发的性质以及在确定系统需要提供的关键业务功能时需要发生的反馈周期。微服务确实增加了指数级的开销和管理的复杂性。因此,新项目将所有代码和逻辑保留在单个代码库中的开销要少得多,因为这样可以更轻松地移动应用程序不同模块的边界。
例如,使用Pizzup,我们可能会从一个非常基本的想法开始,即我们要为客户解决的问题:我们希望人们能够在线订购比萨饼。
当我们开始考虑比萨饼订购问题时,我们将开始确定应用程序所需的不同功能,以满足其需求。我们需要能够管理我们可以制作的不同披萨的列表,我们需要让客户选择一个或多个披萨,处理付款,安排交货等等。我们可能会决定让客户创建帐户将有助于他们下次使用Pizzup时重新订购,并且在与我们的第一批用户交谈之后,我们可能会发现,实时跟踪交付和移动支持肯定会让我们在竞争中获得优势。
一开始的简单需求很快就变成了您需要提供的功能列表。
当您很好地掌握了系统所需的不同服务的角色时,微服务就能很好地工作。如果应用程序的核心需求仍在计算中,那么处理它们就会困难得多。在微服务中重新定义服务交互、api和数据结构确实非常昂贵,因为您可能需要协调更多的移动部分。这就是为什么我们的建议是,在你收集到足够的用户反馈,让你相信客户的基本需求得到了理解和规划之前,让事情保持简单。
但是需要注意的是,构建一个整体很快就会导致复杂的代码,很难分解成更小的部分。尽可能多地尝试识别出清晰的模块,以便稍后从整体中提取它们。您还可以从将逻辑与web UI分离开始,并确保它通过HTTP上的RESTful API与后端进行交互。当您开始将一些API资源转移到不同的服务时,这将使转换到微服务变得更容易。
步骤2:以正确的方式组织团队
到目前为止,构建微服务似乎主要是一项技术事务。您需要将代码库拆分为多个服务,实施正确的模式以使其正常运行并从网络问题中恢复,处理数据一致性,监视服务负载等。将要掌握一堆新概念,但一件事情是不能忽视的是,您将需要重组团队的组织方式。
康威定律:
"设计系统的架构受制于产生这些设计的组织的沟通结构。"
康威定律是可以在所有类型的团队中观察到的真实事物,如果将软件团队与后端团队,前端团队和操作团队分开组织,那么他们最终将交付单独的前端和后端组件给操作团队,以便他们可以在生产中进行管理。
这种类型的结构并不适合微服务,因为每个服务都可以看作是自己的产品,需要独立于其他服务进行发布。相反,您应该创建更小的团队,这些团队拥有开发和维护他们所负责的服务所需的所有能力。亚马逊(Amazon)首席技术官沃纳?沃格尔斯(Werner Vogels)用一句话描述了这种情况:“你构建它,你就运行它”。以这种方式安排您的团队有很大的好处。首先,您的开发人员将更好地理解他们的代码在生产中的影响——这将有助于生成更好的版本,并减少向您的客户发布问题的风险。其次,您的部署将成为每个团队的第二天性,因为他们将能够一起改进代码以及部署管道的自动化。
步骤3:拆分整体以构建微服务架构
当你确定了你的服务的边界,当你弄清楚了如何改变你的团队,使其在能力方面更加垂直,你就可以开始拆分你的整体来构建微服务。下面是当时需要思考的关键点。
使用RESTful API简化服务之间的通信
如果您现在还没有使用RESTful API,那么最好在系统中采用它。正如马丁?福勒(Martin Fowler)所解释的那样,你希望拥有“智能端点和哑管道”。这意味着服务之间的通信协议应该尽可能简单,只负责传输数据而不进行转换。所有神奇的事情都将在端点本身发生——它们接收请求、处理请求并返回响应。
通过避免企业服务总线的复杂性,也可以将微服务与SOA区分开来。微服务体系结构努力使事情尽可能简单,以避免组件之间的紧密耦合。在某些情况下,您可能会发现自己使用带有基于异步消息的通信的事件驱动体系结构。但是,应该再次查看RabbitMQ等基本消息队列服务,并避免增加通过网络传输的消息的复杂性。
划分您的数据结构
在一个整体中拥有用于所有不同功能的单个数据库是很常见的。当用户访问其订单时,您将直接在用户表中查看以显示客户信息,并且该表可能用于填充计费系统管理的发票。这看似合乎逻辑且简单,但是对于微服务,您将希望将服务解耦(以便即使定购系统关闭也可以访问发票),因为它允许您独立于其他发票优化或改进发票表。这意味着每个服务可能最终都有自己的数据存储区来持久存储所需的数据。
显然,这会带来新的问题,因为您最终将在不同的数据库中重复一些数据。在这种情况下,您应该争取最终的一致性,并且可以采用事件驱动的体系结构来帮助跨多个服务同步数据。例如,当客户更新其个人信息时,您的计费和交付跟踪服务可能正在侦听帐户服务发出的事件。收到事件后,这些服务将相应地更新其数据存储。这种事件驱动的体系结构使帐户服务逻辑保持简单,因为它不需要知道所有其他相关服务。它只是告诉系统它做了什么,其他服务则侦听并采取相应的措施。
您还可以选择在帐户服务中保留所有客户信息,并且只在账单和交付服务中保留一个外键引用。然后,他们将与帐户服务进行交互,以在需要时获得相关的客户数据,而不是复制现有记录。对于这些问题并没有一个通用的解决方案,您必须研究每个具体的案例,以确定最佳方法是什么。
为失败构建微服务体系结构
我们已经看到了微服务如何通过单一的体系结构为您提供巨大的好处。它们体积更小,更专业,更容易理解。它们是分离的,这意味着您可以重构一个服务,而不必担心破坏系统的其他组件,或者减慢其他团队的开发。它们还为开发人员提供了更大的灵活性,因为如果需要,他们可以选择不同的技术,而不受其他服务需求的限制。
简而言之,拥有微服务体系结构使开发和维护每个业务功能变得更容易。但是,当您将所有服务放在一起看,以及它们需要如何交互才能完成操作时,事情就变得更加复杂了。系统现在分布有多个故障点,需要解决这些故障点。不仅需要考虑服务没有响应的情况,还需要能够处理较慢的网络响应。从失败中恢复有时也很棘手,因为您需要确保重新启动并运行的服务不会被挂起的消息淹没。
当您开始从您的整体系统中提取功能时,请确保您的设计从一开始就为失败而构建。
强调监控以简化微服务测试
在微服务领域,事情并非那么容易。当涉及到单元测试时,它仍将与整体测试非常相似,并且您在该级别上应该不会感到更多痛苦。但是,当涉及到集成和系统测试时,事情将变得更加困难。您可能必须一起启动多个服务,并启动并运行不同的数据存储,并且您的设置可能需要包括整体式不需要的消息队列。在这种情况下,运行功能测试的成本将大大增加,活动部件的数量不断增加,因此很难预测可能发生的不同类型的故障。
这就是为什么您需要特别强调监视以便能够及早发现问题并做出相应反应的原因。您需要了解不同服务的基准,并且不仅要在它们出现故障时做出反应,而且还要在它们表现异常时做出反应。采用微服务体系结构的一个优势是您的系统应能够应对部分故障,因此,如果您开始发现我们Pizzup应用程序的交付跟踪服务中出现异常,就不会像整体系统那样糟糕。我们的应用程序应经过精心设计,以便所有其他服务都能正确响应,并让我们的客户在恢复实时跟踪的同时订购比萨饼。
采用持续交付来减少部署摩擦
手动将整体式系统投入生产是一项繁琐而冒险的工作,但是可以做到。当然,我们不建议您采用这种方法 ,而是鼓励每个软件团队为所有类型的开发接受持续交付,但是在项目开始时,您可以自己通过命令行进行首次部署。
当您有越来越多的服务需要每天多次部署时,这种方法是不可持续的。因此,在向微服务过渡的过程中,至关重要的一点是,您必须接受持续交付以减少发布失败的风险,并确保团队专注于构建和运行应用程序,而不是被困于部署应用程序。实行连续交付还意味着您的服务在投入生产之前已经通过了验收测试-当然会发生错误,但是随着时间的流逝,您将构建一个强大的测试套件,这将增强您的团队对发布质量的信心。
运行微服务不是冲刺
微服务正在迅速成为流行和广泛采用的行业最佳实践。对于复杂的项目,它们为您构建和部署软件的方式提供了更大的灵活性。它们还有助于识别和规范系统的业务组件,当您有多个团队在同一个应用程序上工作时,这将非常有用。但是,管理分布式系统也存在一些明显的缺点,只有在对服务边界有了清晰的了解之后,才应该拆分整体架构。
建立微服务应该被视为一个旅程,而不是团队的近期目标。从小处着手,以了解分布式系统的技术要求,如何正常处理故障以及扩展单个组件的方法。然后,随着您获得经验和知识,您可以逐渐提取越来越多的服务。
迁移到微服务体系结构不需要一次全力以赴。一种将较小的组件顺序迁移到微服务的迭代策略是更安全的选择。识别已建立的整体应用程序中定义最明确的服务边界,并反复进行工作以将它们解耦到自己的微服务中。
总结
总而言之,微服务是一种策略,它既有利于原始技术代码开发过程,也有利于整个业务组织策略。微服务帮助将团队组织成关注于开发和拥有特定业务功能的单元。这种细粒度的关注提高了整体业务通信和效率。微服务的好处是有权衡的。在迁移到微服务体系结构之前,明确定义服务边界是很重要的。微服务体系结构仍然相当年轻,但它是开发应用程序的一种很有前途的方法,绝对值得研究。只要记住,它可能还不适合您的团队。