微服务概览、误解和误用

【编者的话】 本文从对微服务的误解误用切入,探讨什么是微服务,如何切分微服务。提出告终合传统的DDD,领域驱动设计的理念来帮助定义微服务的边界,值得一读。数据库

【3 天烧脑式基于Docker的CI/CD实战训练营 | 北京站】本次培训围绕基于Docker的CI/CD实战展开,具体内容包括:持续集成与持续交付(CI/CD)概览;持续集成系统介绍;客户端与服务端的 CI/CD 实践;开发流程中引入 CI、CD;Gitlab 和 CI、CD 工具;Gitlab CI、Drone 的使用以及实践经验分享等。编程

过去的三年里,个人工做是Golang,以及云原生的分布式系统架构,包括微服务的咨询师和培训师。在微服务的咨询经验里,在不一样的客户那里由于你们对微服务的误解,我遇到过不少奇怪的事情。我在印度工做,至少在这里,微服务是当下IT行业里最被误解的技术。每一个人都在谈微服务。不少人说他们的应用程序是基于微服务架构的。api

对微服务的误解

这里有几种我据说过的微服务相关的误解:安全

  • 构建HTTP服务,使用Docker容器运行它,而且使用Kubernetes作集群管理,这就是微服务。
  • 使用API Gateway和服务发现以及服务registry,这就是微服务。
  • 使用Spring Boot框架构建HTTP服务,而且使用Netflix OSS,这是微服务。(这来自于Java社区)
  • 使用Azure Service Fabric构建而且运行应用程序,这是微服务。(这来自于.Net社区)
  • 构建轻量的RESTful API,这是微服务。
  • 有不少框架声称是微服务框架。使用这些框架的任意一种来构建应用程序,这就是微服务。

有关微服务的误解还有不少不少不在上述列表中。你可能会使用上述列表里的一些技术来构建微服务,可是使用了某些工具和框架就说本身是微服务,这是没有道理的。网络

微服务是分布式的系统架构,可是那些历来没有开发过度布式系统的开发团队,正在试图像学习新框架那样来学习它,而且基于一些误解来构建应用程序,而后声称本身的应用是基于微服务的。能够看到不少文章的标题都是使用X(Go,Node.js,Java等等)语言,Docker和Kubernetes来构建微服务,讲解构建HTTP服务,在Docker容器里运行,而且使用Kubernetes管理集群,认为这就是微服务。最近在一次个人微服务培训里,一个认为本身是颇有经验的架构师的人,告诉我他是微服务大师,知道有关微服务的全部东西。在我和他的讨论中,我意识到他历来没有据说过DDD和Bounded Context, Event Sourcing, CQRS, gRPC等等,都是从我这里第一次听到这些词。一个历来没有据说过领域建模和DDD Bounded Context的人认为本身是微服务的超级大师。。。架构

和我探讨过的不少创业公司,都宣传他们遵照微服务架构。在和他们的讨论中,我意识到他们称其为微服务,是由于他们的产品有2-5个运行着的应用程序,对于他们来讲每一个应用程序就是一个微服务。面向客户的应用程序是一个微服务,管理应用是另外一个微服务,后台worker是微服务,RESTful API是另外一个微服务。你们基于本身的理解以及本身习惯的方式来构建本身的微服务。让人伤心的是有人甚至没有意识到微服务是一种分布式系统架构。框架

什么是微服务?

首先最为重要的是,微服务是构建分布式系统的架构风格。微服务解决了构建分布式系统的复杂度。在微服务架构里,软件系统由一系列互相独立可部署,小的,模块化的服务组成。每一个微服务围绕一种小型业务能力而构建,由独立团队管理。微服务是某个小型业务能力的独立可部署的组件,微服务架构是构建高度可扩展可进化的软件系统的工程风格,由细粒度的微服务组成。直观上,微服务是能够一块儿工做的小的,自治的服务异步

在绝大多数状况下,一开始应用程序是个单体应用,全部业务能力都放在单个应用程序里,运行在单个进程里。这样的应用程序很容易开发,可是很难有效地扩展,由于应用程序的每一个组件都紧耦合在一块儿。在微服务的架构里,咱们经过组合一系列的自治服务来构建应用程序,每一个服务运行在本身的进程里。这样,就能够很轻松地实现扩展——能够给不一样的服务赋予不一样的扩展能力,独立地升级而且替代每一个服务,同时得到不少其余的架构优点。编程语言

不少人认为微服务是统一的架构框架,是解决全部软件工程问题的银弹。所以你们问的问题相似于,微服务的安全是什么样的。微服务并不是一种统一的架构框架,并非软件工程中全部问题的解决方案,可是它是构建分布式系统的一种方式,这里的核心思想是服务模块化。也就是说,微服务是构建分布式系统的一种思路,须要多种架构方案来实现这样的思路。微服务是已经使用好久的多种架构方案的演进。所以在真实的微服务里,你仍然会使用以前使用过的多种架构方案。分布式

容器化是构建而且运行微服务的很好的方式。若是能够将微服务打包进容器,那么就能够无限扩展而且动态编排微服务,而不需考虑在哪里运行。打包工具,好比Docker,rkt和编排工具,好比Kubernetes,都是容器化微服务的很好的技术。

DDD Aggregate,Bounded Context分离微服务

当从单体架构向微服务架构演进时,最大的问题是怎么将微服务分离出来。如何将一个大型软件系统分解为功能性的组件?微服务的规模多大合适?答案很简单:领域建模。Sam Newman,在他的书“构建微服务”里说,全部走向微服务的路都绕不开领域建模。Eric Evans写的在2003年出版的“领域驱动设计:在软件核内心处理复杂度”是领域建模领域的经典书籍,提供了基于领域模型构建复杂软件系统的指导概要。自从这本书出版以后,Domain-Driven Design (DDD,领域驱动设计)这一术语被业界普遍接受,而且开始使用DDD做为构建软件系统的方式。DDD,介绍了多种构建块,好比Entity,Value Object,Service,Repository,Aggregate和Bounded Context。

Aggregate和Bounded Context是构建微服务的构建块,将决定单个微服务的大小。一般业务实体,好比Order,Customer,Account是Aggregate,它是一张图,包含根实体以及一个或多个其余实体和value对象,是一个最小单元。在微服务里执行事务的更好的方式是经过aggregate实现持久化。Bounded Context是DDD的核心模式,经过将大模型分解为不一样的Bounded Context,从而将业务问题从逻辑上分解成多个子域。Bounded Context封装了单个领域的细节,大型领域模型的子域,就能够剥离为单个微服务。构建微服务的常见战略就是基于每一个Bounded Context构建微服务。每一个微服务使用本身的数据库来持久化某个领域模型的Bounded Context。单个Bounded Context能够包含不少aggregate root,或者单个Bounded Context能够包含一个aggregate root。Order的aggregate root,包含实体包括OrderLine,Customer和Product,value object包括ShippingAdress,PaymentMethod等。在Order的aggregate root图里,Customer实体还能够做为aggregate root,由于它能够做为root实体,获得某个客户的全部信息。Aggregate和Bounded Context是微服务架构里的重要概念,这是构建微服务的基础块,也将决定微服务的大小。简单来讲,微服务是围绕Bounded Context的自治服务

微服务里的挑战

微服务架构的确是构建分布式系统的绝佳方案。可是要记住微服务既不是银弹也不是一种简单的方案。即便使用了微服务来下降构建分布式系统的复杂度,构建分布式系统也毫不是一件轻松的事情。

当从单体应用程序转向微服务架构时,须要解决不少实际的挑战。好比,业务事务可能会分散为几个微服务,由于基于Bounded Context将单体系统分解为多个自治服务。当须要管理数据一致性时,事务可能须要在不少微服务里执行持久化。另外一个挑战是从多个数据库里查询数据。在单体应用里,能够从单个数据库轻松地执行inner join查询。由于单体数据库在分解功能性组件时改为了多个数据库,那么就没法执行inner join,而必须从多个数据库获取数据。这时没有任何中央化的数据库。

使用Event Sourcing和CQRS构建可扩展的微服务

DDD Aggregate和Bounded Context是微服务的基础构建块,可是为构建分布式系统解决实际微服务挑战而选择具体架构时,DDD Aggregate上的事件驱动的交互系统是一种比较好的方案。这里,我强烈推荐使用Event Sourcing,是事件为中心的架构,经过组合各类事件来构成应用程序的状态。Event Sourcing处理不可变事件日志的事件存储,每条日志(某个对象的一次状态变动)表明一种应用程序的状态。由于应用程序里的每次状态变动都做为不可变日志来处理,你能够轻松地排查出应用程序的故障,也能够回到特定时间特定版本的应用程序状态。事件存储像版本控制系统同样。在微服务的架构里,咱们能够将aggregate持久化成事件序列。事件即事实,表明系统里发生的一些操做。这些是不可变的,不会变动或者回退。若是想要在系统里作变动,须要往事件存储里写入新的日志来表示另外一个事件集。事件的示例包括OrderCreated,OrderApproved, OrderShipped, OrderDelivered等等。在Event Sourcing架构里,当你从某个微服务发布一个事件时,其余的微服务能够响应这些事件,而且发布另外的事件集。有时候,事件序列相似于Unix pipe。微服务系统里的单个事务可能会延展到多个微服务里,能够经过构建交互式的微服务来将事务做为事件序列来执行。一个aggregate的每次状态变动都是一个事件,这是系统相关的不可变的事实。为了发布事件让其余微服务知道系统里发生的事情,可使用消息系统,好比Apcera NATS,Kafka,RabbitMQ等等。我我的喜欢的选择是Apcera NATS和Google的Cloud Pub/Sub。事件驱动,交互式的架构是构建大规模可扩展微服务的很好的架构方案。

当使用Event Sourcing将事件序列持久化时,你可能须要一种架构方案来作微服务的查询。架构模式,Command Query Responsibility Segregation(CQRS)是实现微服务查询的理想模式。顾名思义,CQRS将应用程序分为两部分:Command来执行操做变动aggregate的状态,Query为aggregate的视图提供查询模型。咱们还可使用不一样的数据库来作写操做和查询操做。这也让你可以经过将非规则数据装载进读模型的数据仓库来提供高性能的查询模型。NoSQL/NewSQL数据库是很好的读模型数据的存储方案。

虽然Event Sourcing和CQRS,是使用微服务架构实现分布式系统的很好的模式,可是它并不是银弹,也有其自身的限制。你可能须要为一些类型的微服务系统的构建使用不一样的架构风格。可是总的来讲,我认为Event Sourcing,和CQRS的组合,是实现微服务系统的很好的方案。

使用gRPC实现基于API的进程间通讯

在微服务架构里,可能须要进行不少微服务间的进程间通讯。在微服务间进行进程间通讯的两种方案以下:

  • 使用消息系统的异步的事件驱动架构
  • 为每秒百万次的API调用构建大规模高性能的API

经过使用带消息系统的Event Sourcing架构,你能够实现一种异步的事件驱动的架构来管理aggregate的状态。你还可能须要建立API以供微服务间通讯。当你用API执行微服务间的进程间通讯时,性能和可扩展性是很是重要的。应该经过构建高性能的API,从而让你们感受不到网络上正在发生不少通讯。当构建大规模可扩展的系统时,基于JSON的RESTful API不是很好的选择,由于性能挑战会很大,而且缺乏暴露领域特定的操做为API的能力,由于RESTful系统是基于资源的概念的。这里,gRPC,一种高性能,开源的远程过程调用(RPC)框架,能够用来为微服务间的进程间通讯构建大规模可扩展的API。默认来讲,gRPC使用Protocol Buffer做为接口定义语言(IDL),而且做为底层消息交换格式。gRPC是Google的内部框架,Stubby的开源版本,它用来扩展支撑每秒100亿次的API调用。gRPC是微服务架构里基于API的进程间通讯的协议。

微服务的误解和误用

正如本文一开始所说,对于微服务有不少误解,来自于多个开发者社区。我曾经收到过来自不一样客户的要求举办微服务workshop的请求,不少时候,客户会提出课程大纲,这很是让人吃惊,由于大纲上没有任何关于微服务的东西。不少开发者社区将微服务和一些框架和工具绑定在一块儿。不少Java开发人员坚信使用Spring Boot构建RESTful API而且利用Netflix OSS的一些工具就是微服务,而另外一些来自.NET社区的人认为使用Azure Service Fabric运行的应用程序是微服务。也有人问我RESTful服务和微服务的区别,由于不少人认为构建一些轻量的RESTful API就是微服务。另一些人认为使用Spring Boot构建API是微服务。我也不知道从哪里开始Spring Boot被误解为微服务的。

我感受到你们只是听到了微服务这个词,而且将它和一些工具以及框架联系在一块儿,并无理解这种变革性架构的真正精神和意图。这样的状况和架构模式,好比SOA以及工程实践,好比Agile非常相似。我知道不少公司声称本身遵守敏捷工程实践,仅仅由于他们使用了Scrum流程,而其实他们仍然以很是传统的方式构建应用程序。TDD也是同样,不少企业在编写生产代码以后才写单元测试,而后尝试获得想要达到的测试覆盖率,就认为本身在使用TDD开发应用程序。即便是一个小众社区,可是不少人在引入技术,模式和实践的时候,仅仅是为了声称使用了这些东西而已。

微服务的确是构建大规模可扩展应用程序的伟大的架构风格。微服务还适合构建互联网规模的应用程序,好比Netflix,Uber,Amazon,eBay等等。可是它不是全部人都适合使用的,也并不是银弹。虽然微服务是构建大规模可扩展应用程序,包括面向大众的互联网级别的应用程序的正确的架构方案,可是对于大多数其余类型的应用程序,特别是构建企业级应用程序(有复杂的领域模型)来讲,它多是错误的选择。我我的不推荐用微服务来作复杂的业务应用,由于这些应用有很是复杂的领域模型。可是微服务是领域模型没那么复杂的,大规模可扩展的,而且可扩展是最具挑战因素,也是成功要素的应用程序的理想选择。对于一些类型的应用程序,微服务架构风格的实现可能会带来不少性能问题,而且增长了系统的复杂度,最终可能致使失败。仅仅由于和热门技术沾边就使用微服务可能会给你的系统带来不少反作用。

改进单体应用程序

在个人咨询经验里,我认为在绝大多数用例里,不须要使用微服务架构,适合大多数应用程序的更好的方案是折中方案。你可使用混合方案来解决问题。你的企业可能并无Google,Amazon,Netflix,Uber,eBay,Square等公司这样的技术能力。在你的公司里你的问题是独特的。架构方案必需要可以解决问题,而且使用它解决你本身的独特问题,而不是为了用而用。

你能够按照以下方式改进已有的单体应用程序:将单体应用程序分解为多个系统,而不是盲目遵照微服务的概要,选择使用混合架构方案,使用DevOps文化以及现代化的CI/CD pipeline。微服务的最大优点是模块化。当构建新的应用程序时,能够经过应用模块化系统设计原则,而不是微服务架构,来架构系统。好比,Go编程语言的打包生态系统让你可以使用更好的模块化思路来设计应用程序。若是以后你想要迁移到微服务来独立扩展模块和团队的话,该方案还让你能更容易地迁移到微服务上。最好是从使用模块化系统设计原则实现单体应用开始,而后当系统和团队发展时,能够在确实须要的时候转向微服务架构。

要记住你的公司和产品是独一无二的。不要成为技术,模式和实践的盲目追随者,使用折中方案解决本身的问题。为了使用技术而使用是没有任何意义的。

原文连接:Microservices: Overview, Misinterpretations and Misuses(翻译:崔婧雯)===========================译者介绍崔婧雯,现就任于IBM,高级软件工程师,负责IBM WebSphere业务流程管理软件的系统测试工做。曾就任于VMware从事桌面虚拟化产品的质量保证工做。对虚拟化,中间件技术,业务流程管理有浓厚的兴趣。

相关文章
相关标签/搜索