在本文中,我计划介绍微服务架构(MSA)的关键架构概念,以及如何在实践中使用这些架构原理。
微服务是软件体系结构领域最流行的流行语之一。 关于微服务的基础知识和好处的学习材料很多,但是关于如何在现实的企业场景中使用微服务的资源很少。
在本文中,我将介绍微服务架构(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架构学习分享,希望这使你对如何在企业中使用微服务有了更清晰的认识。
原文:https://www.cnblogs.com/youruike1/p/12111585.html