在本文中,我计划介绍微服务架构(MSA)的关键架构概念,以及如何在实践中使用这些架构原理。html
微服务是软件体系结构领域最流行的流行语之一。 关于微服务的基础知识和好处的学习材料不少,可是关于如何在现实的企业场景中使用微服务的资源不多。java
在本文中,我将介绍微服务架构(MSA)的关键架构概念,以及如何在实践中使用这些架构原理。数据库
总体架构安全
企业软件应用程序旨在知足众多业务需求;给定的软件应用程序提供数百种功能,全部这些功能都堆积在单个总体应用程序中。例如,ERP,CRM和其余各类软件系统被构建为具备数百种功能的总体。如此庞大的软件应用程序的部署,故障排除,扩展和升级是一场噩梦。服务器
面向服务的体系结构(SOA)旨在经过引入服务的概念,应用程序提供的类似功能的汇集和分组来克服某些上述限制。使用SOA,能够将软件应用程序设计为粗粒度服务的组合。可是,在SOA中,服务范围很是普遍。这致使具备数十种操做(功能)的复杂而庞大的服务,以及复杂的消息格式和标准(例如:全部WS *标准)。网络
总体架构架构
在大多数状况下,SOA中的服务彼此独立。 可是它们与全部其余服务一块儿部署在同一运行时中(考虑一下将多个Web应用程序部署到同一Tomcat实例中)。 与单片软件应用程序类似,这些服务具备经过累积各类功能随着时间而增加的习惯。 从字面上看,这将这些应用程序变成了与通用总体应用程序(如ERP)没有区别的总体结构。 该图显示了包含多个服务的零售软件应用程序。 全部这些服务都部署到同一应用程序运行时中。 所以,这是一个总体架构的很好的例子。 这是基于总体架构的应用程序的一些特征。负载均衡
微服务架构(MSA)的基础是将单个应用程序开发为一组小型独立服务,这些独立服务在其本身的流程中运行,独立开发和部署。框架
在微服务架构的大多数定义中,将其解释为将总体中可用的服务隔离为一组独立服务的过程。可是,在我看来,微服务不只仅是将总体中可用的服务拆分为独立的服务。异步
关键思想是,经过查看总体提供的功能,咱们能够肯定所需的业务能力。而后,能够将那些业务功能实现为彻底独立,细粒度且自包含的(微)服务。它们可能在不一样的技术堆栈之上实现,而且每种服务都针对很是特定且有限的业务范围。
所以,咱们上面解释的在线零售系统场景能够经过微服务架构实现,以下图所示。经过微服务体系结构,零售软件应用程序被实现为一组微服务。所以,正如你在下面看到的那样,根据业务需求,还有一个总体服务是根据总体中存在的原始服务集建立的。所以,很明显,使用微服务体系结构是超出了总体中服务拆分的范围。
微服务架构
让咱们深刻研究微服务的关键体系结构原理,更重要的是,让咱们集中讨论如何在实践中使用它们。
你可能正在使用Microservices Architecture从头开始构建软件应用程序,或者可能将现有的应用程序/服务转换为微服务。 不管哪一种方式,正确决定微服务的大小,范围和功能都是很是重要的。 这多是你在实践中实现微服务架构时最初遇到的最困难的事情。
让咱们讨论与微服务的大小,范围和功能有关的一些关键的实际问题和误解。
那么,咱们应该如何在微服务架构中正确设计服务?
在咱们的零售用例中,你能够发现咱们已经将总体的功能分为四个不一样的微服务,即“库存”,“会计”,“运输”和“商店”。 他们正在解决一个有限但集中的业务范围,以便每一个服务彼此彻底分离,并确保开发和部署的敏捷性。
在单片应用程序中,使用功能调用或语言级方法调用来调用不一样处理器/组件的业务功能。 在SOA中,这已转向更加松散耦合的Web服务级别消息传递,该消息传递主要基于SOAP并基于HTTP,JMS等不一样协议。 具备数十种操做和复杂消息模式的Web服务是Web服务普及的主要阻力。 对于微服务架构,要求具备简单轻量的消息传递机制。
对于Microservices Architecture中的同步消息传递(客户端但愿服务及时响应并等待它得到响应),REST是一致的选择,由于它提供了一种简单的消息传递样式,该消息传递样式基于资源API样式经过HTTP请求响应实现。 所以,大多数微服务实现都使用HTTP以及基于资源API的样式(每种功能都由一种资源表示,而且在这些资源之上执行操做)。
对于某些微服务场景,要求使用异步消息传递技术(客户端不但愿当即响应,或者根本不接受响应)。 在这种状况下,异步消息传递协议如AMQP,STOMP或MQTT被普遍使用。
消息格式-JSON,XML,Thrift,ProtoBuf,Avro
roservices是另外一个关键因素。 传统的单片应用程序使用复杂的二进制格式,基于SOA / Web服务的应用程序使用基于复杂消息格式(SOAP)和架构(xsd)的文本消息。 在大多数基于微服务的应用程序中,它们使用简单的基于文本的消息格式,例如HTTP资源API样式之上的JSON和XML。 在咱们须要二进制消息格式的状况下(文本消息在某些用例中可能变得冗长),微服务能够利用二进制消息格式,例如二进制Thrift,ProtoBuf或Avro。
当你将业务功能实现为服务时,你须要定义和发布服务合同。 在传统的总体应用程序中,咱们几乎找不到用于定义应用程序业务功能的功能。 在SOA / Web服务世界中,WSDL用于定义服务协定,可是,众所周知,WSDL并非复杂的且与SOAP紧密耦合,所以不是定义微服务协定的理想解决方案。
因为咱们是基于REST架构样式构建微服务的,所以咱们可使用相同的REST API定义技术来定义微服务的契约。 所以,微服务使用标准的REST API定义语言(例如Swagger和RAML)来定义服务合同。
对于其余不基于HTTP / REST的微服务实现(例如Thrift),咱们可使用协议级别的接口定义语言(IDL)(例如:Thrift IDL)。
在微服务体系结构中,软件应用程序被构建为一套独立的服务。所以,为了实现业务用例,须要在不一样的微服务/流程之间具备通讯结构。这就是微服务之间的服务间/流程通讯如此重要的缘由。
在SOA实现中,使用企业服务总线(ESB)能够促进服务之间的服务间通讯,而且大多数业务逻辑位于中间层(消息路由,转换和编排)。可是,微服务体系结构促进消除中央消息总线/ ESB,并将“智能性”或业务逻辑转移到服务和客户端(称为智能端点)。
因为微服务使用诸如HTTP,JSON等标准协议,所以在微服务之间进行通讯时,与不一样协议集成的要求极小。微服务通讯中的另外一种替代方法是使用轻量级消息总线或网关,路由功能最少,并充当``哑管道'',而网关上未实现任何业务逻辑。基于这些样式,微服务体系结构中出现了几种通讯模式。
在点对点样式中,整个消息路由逻辑都驻留在每一个端点上,而且服务能够直接进行通讯。 每一个微服务都公开一个REST API,给定的微服务或外部客户端能够经过其REST API调用另外一个微服务。
具备点对点链接的服务间通讯
显然,该模型适用于相对简单的基于微服务的应用程序,可是随着服务数量的增长,这将变得极为复杂。 毕竟,这就是在传统SOA实现中使用ESB的确切缘由:摆脱凌乱的点对点集成连接。 让咱们尝试总结微服务通讯的点对点样式的主要缺点。
API网关样式背后的关键思想是使用轻量级消息网关做为全部客户端/消费者的主要入口点,并在网关级别实现常见的非功能性要求。 一般,API网关容许你经过REST / HTTP使用托管API。 所以,在这里,咱们能够将经过API-GW做为托管服务实现为微服务的业务功能公开。 实际上,这是微服务架构和API管理的结合,可为你提供一箭双鵰的体验。
全部微服务都经过API-GW公开在咱们的零售业务场景中,如上图所示,全部微服务都经过API-GW公开,这是全部客户端的单一入口点。 若是微服务想要使用另外一个微服务,则也须要经过API-GW来完成。
API-GW样式具备如下优势:
API-GW样式极可能是大多数微服务实现中使用最普遍的模式。
微服务能够与异步消息传递场景集成,例如单向请求和使用队列或主题的发布-订阅消息传递。 给定的微服务能够是消息生产者,而且能够异步将消息发送到队列或主题。 而后,消费微服务能够消费来自队列或主题的消息。 这种样式使消息生产者与消息使用者分离,中间消息代理将缓冲消息,直到使用者可以处理它们为止。 生产者微服务彻底不了解消费者微服务。
使用pub-sub的基于异步消息传递的集成
消费者/生产者之间的通讯经过基于异步消息传递标准(例如AMQP,MQTT等)的消息代理来促进。
在总体架构中,应用程序将数据存储在单个集中式数据库中,以实现应用程序的各类功能。
单一应用程序使用中央数据库来实现其全部功能。在微服务体系结构中,功能分散在多个微服务之间,若是咱们使用相同的中央数据库,则微服务将再也不彼此独立(例如,若是 数据库架构已从给定的微服务更改,这将破坏其余几个服务)。 所以,每一个微服务都必须具备本身的数据库。
每一个微服务都有本身的私有数据库
这是在微服务架构中实施分散数据管理的关键方面。
分散的数据管理为你提供了彻底解耦的微服务,而且能够自由选择不一样的数据管理技术(SQL或NoSQL等,每种服务使用不一样的数据库管理系统)。 可是,对于涉及多个微服务的复琐事务用例,必须使用每一个服务提供的API来实现事务行为,而且逻辑位于客户端或中介(GW)级别。
微服务架构支持分散式治理。
那么,微服务环境中的治理到底意味着什么? 在微服务架构中,微服务被构建为具备各类技术和平台的彻底独立和解耦的服务。 所以,无需为服务设计和开发定义通用标准。 所以,咱们能够将微服务的去中心化治理功能总结以下:
在微服务架构中,你须要处理的微服务数量很是多。并且,因为微服务的快速和敏捷开发/部署性质,它们的位置会动态变化。所以,你须要在运行时找到微服务的位置。解决此问题的方法是使用服务注册表。
服务注册
服务注册表包含微服务实例及其位置。微服务实例在启动时在服务注册表中注册,并在关机时注销。消费者能够经过服务注册表找到可用的微服务及其位置。
服务发现
为了找到可用的微服务及其位置,咱们须要一种服务发现机制。服务发现机制有两种类型,客户端发现和服务器端发现。让咱们仔细看看那些服务发现机制。
客户端发现-经过这种方法,客户端或API-GW经过查询服务注册表来获取服务实例的位置。
在微服务架构中,你须要处理的微服务数量很是多。 并且,因为微服务的快速和敏捷开发/部署性质,它们的位置会动态变化。 所以,你须要在运行时找到微服务的位置。 解决此问题的方法是使用服务注册表。
服务注册
服务注册表包含微服务实例及其位置。 微服务实例在启动时在服务注册表中注册,并在关机时注销。 消费者能够经过服务注册表找到可用的微服务及其位置。
为了找到可用的微服务及其位置,咱们须要一种服务发现机制。 服务发现机制有两种类型,客户端发现和服务器端发现。 让咱们仔细看看那些服务发现机制。
客户端发现-经过这种方法,客户端或API-GW经过查询服务注册表来获取服务实例的位置。
客户端发现
服务器端发现-使用这种方法,客户端/ API-GW将请求发送到在已知位置运行的组件(例如负载均衡器)。 该组件调用服务注册表并肯定微服务的绝对位置。
客户端发现
诸如Kubernetes(http://kubernetes.io/v1.1/docs/user-guide/services.html)之类的微服务部署解决方案提供了服务端发现机制。
在微服务架构方面,微服务的部署起着相当重要的做用,而且具备如下关键要求:
Docker(一种开放源代码引擎,可以让开发人员和系统管理员在Linux环境中部署自给自足的应用程序容器)提供了一种很好的方式来部署微服务以知足上述要求。 涉及的关键步骤以下:
Kubernetes经过容许将Linux容器集群做为一个系统进行管理,跨多个主机管理和运行Docker容器,提供容器的共置,服务发现和复制控制功能,扩展了Docker的功能。 如你所见,大多数这些功能在咱们的微服务环境中也是必不可少的。 所以,使用Kubernetes(在Docker之上)进行微服务部署已成为一种极其强大的方法,尤为是对于大规模微服务部署。
将微服务构建和部署为容器。
在实际场景中使用微服务时,保护微服务是很是广泛的要求。 在进入微服务安全性以前,让咱们快速看一下咱们一般如何在总体应用程序级别上实现安全性。
那么,咱们能够直接将此模式转换为微服务架构吗? 是的,但这须要在每一个微服务级别实现的安全组件,该组件正在与集中式/共享用户存储库进行对话并检索所需的信息。 这是解决微服务安全性问题的很是乏味的方法。 相反,咱们能够利用普遍使用的API安全标准(例如OAuth2和OpenID Connect)为咱们的微服务安全问题找到更好的解决方案。 在深刻探讨这一点以前,让我概述一下每一个标准的目的以及如何使用它们
·OpenIDConnect的行为相似于OAuth,但除了访问令牌外,受权服务器还会发布一个ID令牌,其中包含有关用户的信息。 这一般由JWT(JSON Web令牌)实现,并由受权服务器签名。 所以,这确保了受权服务器和客户端之间的信任。 所以,JWT令牌被称为“按值令牌”,由于它包含用户的信息,而且显然在内部网络以外使用它是不安全的。
具备OAuth2和OpenID Connect的微服务安全性
如上图所示,这些是实现微服务安全性涉及的关键步骤:
微服务中的交易支持如何?实际上,支持跨多个微服务的分布式事务是很是复杂的任务。微服务架构自己鼓励服务之间的无事务协调。
想法是,给定的服务是彻底独立的,而且基于单一责任原则。跨多个微服务进行分布式事务的需求一般是微服务体系结构中设计缺陷的征兆,一般能够经过重构微服务的范围来解决。可是,若是必须在多个服务之间分配事务,则能够经过在每一个微服务级别引入“补偿操做”来实现这种状况。关键思想是,给定的微服务基于单一职责原则,若是给定的微服务没法执行给定的操做,咱们能够认为这是整个微服务的失败。而后,必须经过调用这些微服务的相应补偿操做来撤消全部其余(上游)操做。
失败的设计
微服务架构引入了一组分散的服务,而且与单片设计相比,增长了在每一个服务级别出现故障的可能性。 给定的微服务可能会因为网络问题,基础资源的不可用等缘由而失败。不可用或无响应的微服务不该致使整个基于微服务的应用程序崩溃。 所以,微服务应该是容错的,可以在可能的状况下恢复,而且客户端必须妥善处理它。
另外,因为服务随时可能发生故障,所以可以快速检测(实时监视)故障并在可能的状况下自动恢复服务也很重要。
在微服务上下文中,有几种经常使用的模式来处理错误。context.
当你对微服务进行外部调用时,你须要为每次调用配置一个故障监视器组件,而且当故障达到某个阈值时,该组件将中止对该服务的任何进一步调用(使电路跳闸)。 在必定数量的请求处于打开状态(你能够配置)以后,将电路更改回关闭状态。
这种模式很是有用,可避免没必要要的资源消耗,因为超时而致使的请求延迟,而且还使咱们有机会监视系统(基于活动的开路状态)。
因为微服务应用程序包含微服务的数量,所以基于微服务的应用程序一部分的故障不该影响其他的应用程序。 隔板模式是关于隔离应用程序的不一样部分的,所以应用程序中服务的故障不会影响任何其余服务。
超时模式是一种机制,当你认为微服务不会响应时,它可让你中止等待微服务的响应。 你能够在此处配置但愿等待的时间间隔。
那么,咱们在哪里以及如何在微服务中使用这些模式? 在大多数状况下,这些模式中的大多数都适用于网关级别。 这意味着当微服务不可用或没有响应时,在网关级别,咱们能够决定是否使用断路器或超时模式将请求发送到微服务。 一样,在网关级别实现诸如隔板等模式也是很是重要的,由于它是全部客户端请求的单个入口点,所以赠与服务的失败不该影响其余微服务的调用。
另外,网关能够用做中心点,当经过网关调用每一个微服务时,咱们能够得到状态并监视每一个微服务。
咱们已经讨论了微服务架构的各类特征,以及如何在现代企业IT环境中实现它们。可是,咱们应该记住,微服务不是万能药。流行语概念的盲目适应将没法解决你的“实际”企业IT问题。正如你在整个博客文章中所看到的那样,微服务具备不少优点,咱们应该加以利用。可是,咱们还必须记住,用微服务解决全部企业IT问题是不现实的。例如,微服务架构促进了消除ESB做为中央总线的发展,可是在现实世界中,有不少不基于微服务的现有应用程序/服务。所以,要与它们集成,咱们须要某种集成总线。所以,理想状况下,微服务和其余企业体系结构概念(例如集成)的混合方法将更为现实。我将在另外一篇博客文章中进一步讨论它们。
本文灵感源于优锐课java架构学习分享,但愿这使你对如何在企业中使用微服务有了更清晰的认识。