实践中的微服务:从架构到部署

在本文中,我计划介绍微服务架构(MSA)的关键架构概念,以及如何在实践中使用这些架构原理。html

微服务是软件体系结构领域最流行的流行语之一。 关于微服务的基础知识和好处的学习材料不少,可是关于如何在现实的企业场景中使用微服务的资源不多。java

在本文中,我将介绍微服务架构(MSA)的关键架构概念,以及如何在实践中使用这些架构原理。数据库

总体架构安全

企业软件应用程序旨在知足众多业务需求;给定的软件应用程序提供数百种功能,全部这些功能都堆积在单个总体应用程序中。例如,ERP,CRM和其余各类软件系统被构建为具备数百种功能的总体。如此庞大的软件应用程序的部署,故障排除,扩展和升级是一场噩梦。服务器

面向服务的体系结构(SOA)旨在经过引入服务的概念,应用程序提供的类似功能的汇集和分组来克服某些上述限制。使用SOA,能够将软件应用程序设计为粗粒度服务的组合。可是,在SOA中,服务范围很是普遍。这致使具备数十种操做(功能)的复杂而庞大的服务,以及复杂的消息格式和标准(例如:全部WS *标准)。网络

 

总体架构架构

在大多数状况下,SOA中的服务彼此独立。 可是它们与全部其余服务一块儿部署在同一运行时中(考虑一下将多个Web应用程序部署到同一Tomcat实例中)。 与单片软件应用程序类似,这些服务具备经过累积各类功能随着时间而增加的习惯。 从字面上看,这将这些应用程序变成了与通用总体应用程序(如ERP)没有区别的总体结构。 该图显示了包含多个服务的零售软件应用程序。 全部这些服务都部署到同一应用程序运行时中。 所以,这是一个总体架构的很好的例子。 这是基于总体架构的应用程序的一些特征。负载均衡

  • ·总体应用程序是做为一个单元进行设计,开发和部署的。
  • ·总体应用极为复杂; 这致使维护,升级和添加新功能的噩梦。
  • ·很难使用Monolithic体系结构来实践敏捷开发和交付方法。
  • ·须要从新部署整个应用程序以更新其中的一部分。
  • ·该应用程序必须按单个单元进行扩展,从而难以管理相互冲突的资源需求(例如,一项服务须要更多的CPU,而另外一项则须要更多的内存)
  • ·一项不稳定的服务可能会致使整个应用程序崩溃。
  • ·采用新技术和框架真的很困难,由于全部功能都必须基于同类技术/框架。

微服务架构

微服务架构(MSA)的基础是将单个应用程序开发为一组小型独立服务,这些独立服务在其本身的流程中运行,独立开发和部署。框架

在微服务架构的大多数定义中,将其解释为将总体中可用的服务隔离为一组独立服务的过程。可是,在我看来,微服务不只仅是将总体中可用的服务拆分为独立的服务。异步

关键思想是,经过查看总体提供的功能,咱们能够肯定所需的业务能力。而后,能够将那些业务功能实现为彻底独立,细粒度且自包含的(微)服务。它们可能在不一样的技术堆栈之上实现,而且每种服务都针对很是特定且有限的业务范围。

所以,咱们上面解释的在线零售系统场景能够经过微服务架构实现,以下图所示。经过微服务体系结构,零售软件应用程序被实现为一组微服务。所以,正如在下面看到的那样,根据业务需求,还有一个总体服务是根据总体中存在的原始服务集建立的。所以,很明显,使用微服务体系结构是超出了总体中服务拆分的范围。

 

微服务架构

让咱们深刻研究微服务的关键体系结构原理,更重要的是,让咱们集中讨论如何在实践中使用它们。

设计微服务:大小,范围和功能

可能正在使用Microservices Architecture从头开始构建软件应用程序,或者可能将现有的应用程序/服务转换为微服务。 不管哪一种方式,正确决定微服务的大小,范围和功能都是很是重要的。 这多是在实践中实现微服务架构时最初遇到的最困难的事情。

让咱们讨论与微服务的大小,范围和功能有关的一些关键的实际问题和误解。

  • ·代码行/团队规模是糟糕的指标:关于基于实现的代码行或团队规模(即两个比萨饼团队)肯定微服务规模的讨论不少。 可是,这些指标被认为是很是不切实际和糟糕的指标,由于咱们仍然可使用更少的代码/具备两个比萨饼的团队来开发服务,但彻底违反了微服务架构的原则。
  • ·“微”是一个误导性术语:大多数开发人员倾向于认为他们应该尝试使服务尽量小。 这是一个误解。
  • ·SOA上下文:在SOA上下文中,服务一般实现为总体,并支持数十种操做/功能。 所以,拥有相似于SOA的服务并将其从新命名为微服务并不会给带来微服务架构的任何好处。

那么,咱们应该如何在微服务架构中正确设计服务?

设计微服务准则

  • ·“单一责任原则”(SRP):微服务的业务范围有限且重点突出,能够帮助咱们知足服务开发和交付中的敏捷性。
  • ·在微服务的设计阶段,咱们应该找到它们的边界并将其与业务功能(在域驱动设计中也称为受限上下文)保持一致。
  • ·确保微服务设计可确保服务的敏捷/独立开发和部署。
  • ·咱们的重点应该放在微服务的范围上,而不是缩小服务范围。 服务的(正确)大小应该是促进给定业务能力所需的大小。
  • ·与SOA中的服务不一样,给定的微服务应具备不多的操做/功能和简单的消息格式。
  • ·一般,从较长的服务边界开始,而后随着时间的流逝而重构为较小的服务边界(根据业务需求)一般是一个好习惯。

在咱们的零售用例中,能够发现咱们已经将总体的功能分为四个不一样的微服务,即“库存”,“会计”,“运输”和“商店”。 他们正在解决一个有限但集中的业务范围,以便每一个服务彼此彻底分离,并确保开发和部署的敏捷性。

微服务中的消息传递

在单片应用程序中,使用功能调用或语言级方法调用来调用不一样处理器/组件的业务功能。 在SOA中,这已转向更加松散耦合的Web服务级别消息传递,该消息传递主要基于SOAP并基于HTTP,JMS等不一样协议。 具备数十种操做和复杂消息模式的Web服务是Web服务普及的主要阻力。 对于微服务架构,要求具备简单轻量的消息传递机制。

同步消息传递-REST,节流

对于Microservices Architecture中的同步消息传递(客户端但愿服务及时响应并等待它得到响应),REST是一致的选择,由于它提供了一种简单的消息传递样式,该消息传递样式基于资源API样式经过HTTP请求响应实现。 所以,大多数微服务实现都使用HTTP以及基于资源API的样式(每种功能都由一种资源表示,而且在这些资源之上执行操做)。

 

使用REST接口公开微服务

使用Thrift(你能够在其中定义微服务的接口定义),做为REST / HTTP同步消息传递的替代方法。

异步消息传递-AMQP,STOMP,MQTT

对于某些微服务场景,要求使用异步消息传递技术(客户端不但愿当即响应,或者根本不接受响应)。 在这种状况下,异步消息传递协议如AMQP,STOMP或MQTT被普遍使用。

消息格式-JSON,XML,Thrift,ProtoBuf,Avro

roservices是另外一个关键因素。 传统的单片应用程序使用复杂的二进制格式,基于SOA / Web服务的应用程序使用基于复杂消息格式(SOAP)和架构(xsd)的文本消息。 在大多数基于微服务的应用程序中,它们使用简单的基于文本的消息格式,例如HTTP资源API样式之上的JSON和XML。 在咱们须要二进制消息格式的状况下(文本消息在某些用例中可能变得冗长),微服务能够利用二进制消息格式,例如二进制Thrift,ProtoBuf或Avro。

服务合同-定义服务接口-Swagger,RAML,节俭

将业务功能实现为服务时,须要定义和发布服务合同。 在传统的总体应用程序中,咱们几乎找不到用于定义应用程序业务功能的功能。 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的确切缘由:摆脱凌乱的点对点集成连接。 让咱们尝试总结微服务通讯的点对点样式的主要缺点。

  • ·必须在每一个微服务级别实现最终用户身份验证,限制,监视等非功能性要求。
  • ·因为复制了通用功能,所以每一个微服务实现均可能变得复杂。
  • ·服务与客户端之间的全部通讯都没法控制(即便用于监视,跟踪或筛选)
  • ·对于大规模微服务实现,一般将直接通讯样式视为微服务反模式。

所以,对于复杂的微服务用例,咱们可使用轻量级的中央消息传递总线,而不是使用点对点链接或中央ESB,它能够为微服务提供抽象层,并能够用于实现各类非功能性 能力。 此样式称为API网关样式

API网关样式

API网关样式背后的关键思想是使用轻量级消息网关做为全部客户端/消费者的主要入口点,并在网关级别实现常见的非功能性要求。 一般,API网关容许经过REST / HTTP使用托管API。 所以,在这里,咱们能够将经过API-GW做为托管服务实现为微服务的业务功能公开。 实际上,这是微服务架构和API管理的结合,可为提供一箭双鵰的体验。

全部微服务都经过API-GW公开在咱们的零售业务场景中,如上图所示,全部微服务都经过API-GW公开,这是全部客户端的单一入口点。 若是微服务想要使用另外一个微服务,则也须要经过API-GW来完成。

API-GW样式具备如下优势:

  • ·可以在网关级别为现有微服务提供所需的抽象。 例如,API网关能够提供每一个客户端不一样的API,而不是提供一种千篇一概的样式API
  • ·网关级别的轻量级消息路由/转换。
  • ·应用非功能性功能(例如安全性,监视和限制)的中心位置。
  • ·经过使用API-GW模式,因为全部非功能性需求都在网关级别实现,所以微服务变得更加轻量级。

API-GW样式极可能是大多数微服务实现中使用最普遍的模式。

消息代理样式

微服务能够与异步消息传递场景集成,例如单向请求和使用队列或主题的发布-订阅消息传递。 给定的微服务能够是消息生产者,而且能够异步将消息发送到队列或主题。 而后,消费微服务能够消费来自队列或主题的消息。 这种样式使消息生产者与消息使用者分离,中间消息代理将缓冲消息,直到使用者可以处理它们为止。 生产者微服务彻底不了解消费者微服务。

使用pub-sub的基于异步消息传递的集成

消费者/生产者之间的通讯经过基于异步消息传递标准(例如AMQP,MQTT等)的消息代理来促进。

分散数据管理

在总体架构中,应用程序将数据存储在单个集中式数据库中,以实现应用程序的各类功能。

单一应用程序使用中央数据库来实现其全部功能。在微服务体系结构中,功能分散在多个微服务之间,若是咱们使用相同的中央数据库,则微服务将再也不彼此独立(例如,若是 数据库架构已从给定的微服务更改,这将破坏其余几个服务)。 所以,每一个微服务都必须具备本身的数据库。

每一个微服务都有本身的私有数据库

这是在微服务架构中实施分散数据管理的关键方面。

  • ·每一个微服务均可以有一个私有数据库来保留实现其提供的业务功能所需的数据。
  • ·给定的微服务只能访问专用私有数据库,而不能访问其余微服务的数据库。
  • ·在某些业务场景中,你可能必须为单个事务更新多个数据库。 在这种状况下,其余微服务的数据库应仅经过其服务API进行更新(不容许直接访问该数据库)

分散的数据管理为你提供了彻底解耦的微服务,而且能够自由选择不一样的数据管理技术(SQLNoSQL等,每种服务使用不一样的数据库管理系统)。 可是,对于涉及多个微服务的复琐事务用例,必须使用每一个服务提供的API来实现事务行为,而且逻辑位于客户端或中介(GW)级别。

分散治理

微服务架构支持分散式治理。

  • 一般,“治理”是指创建和增强人员和解决方案如何共同协做以实现组织目标。 在SOA的背景下,SOA治理指导可重用服务的开发,肯定如何设计和开发服务以及这些服务将随着时间的变化而变化。 它在服务的提供者和这些服务的消费者之间创建协议,告诉消费者他们能够指望什么以及提供者他们有义务提供什么。 在SOA治理中,有两种经常使用的治理类型:

那么,微服务环境中的治理到底意味着什么? 在微服务架构中,微服务被构建为具备各类技术和平台的彻底独立和解耦的服务。 所以,无需为服务设计和开发定义通用标准。 所以,咱们能够将微服务的去中心化治理功能总结以下:

  • ·在微服务架构中,不须要进行集中的设计时治理。
  • ·微服务能够自行决定其设计和实现。
  • ·微服务架构促进了公共/可重用服务的共享。
  • ·某些运行时治理方面,例如SLA,节流,监视,通用安全要求和服务发现,能够在API-GW级别上实现。

服务注册和服务发现

在微服务架构中,你须要处理的微服务数量很是多。并且,因为微服务的快速和敏捷开发/部署性质,它们的位置会动态变化。所以,你须要在运行时找到微服务的位置。解决此问题的方法是使用服务注册表。

服务注册

服务注册表包含微服务实例及其位置。微服务实例在启动时在服务注册表中注册,并在关机时注销。消费者能够经过服务注册表找到可用的微服务及其位置。

服务发现

为了找到可用的微服务及其位置,咱们须要一种服务发现机制。服务发现机制有两种类型,客户端发现和服务器端发现。让咱们仔细看看那些服务发现机制。

客户端发现-经过这种方法,客户端或API-GW经过查询服务注册表来获取服务实例的位置。

在微服务架构中,你须要处理的微服务数量很是多。 并且,因为微服务的快速和敏捷开发/部署性质,它们的位置会动态变化。 所以,须要在运行时找到微服务的位置。 解决此问题的方法是使用服务注册表。

服务注册

服务注册表包含微服务实例及其位置。 微服务实例在启动时在服务注册表中注册,并在关机时注销。 消费者能够经过服务注册表找到可用的微服务及其位置。

服务发现

为了找到可用的微服务及其位置,咱们须要一种服务发现机制。 服务发现机制有两种类型,客户端发现和服务器端发现。 让咱们仔细看看那些服务发现机制。

客户端发现-经过这种方法,客户端或API-GW经过查询服务注册表来获取服务实例的位置。

客户端发现

服务器端发现-使用这种方法,客户端/ API-GW将请求发送到在已知位置运行的组件(例如负载均衡器)。 该组件调用服务注册表并肯定微服务的绝对位置。

客户端发现

诸如Kubernetes(http://kubernetes.io/v1.1/docs/user-guide/services.html)之类的微服务部署解决方案提供了服务端发现机制。

部署方式

在微服务架构方面,微服务的部署起着相当重要的做用,而且具备如下关键要求:

  • 可以独立于其余微服务进行部署/取消部署。
  • 必须可以在每一个微服务级别进行扩展(给定的服务可能比其余服务得到更多的流量)。
  • 快速构建和部署微服务。
  • 一个微服务中的故障不得影响任何其余服务。

Docker(一种开放源代码引擎,可以让开发人员和系统管理员在Linux环境中部署自给自足的应用程序容器)提供了一种很好的方式来部署微服务以知足上述要求。 涉及的关键步骤以下:

  • ·将微服务打包为(Docker)容器映像。
  • ·将每一个服务实例部署为一个容器。
  • ·缩放是根据更改容器实例的数量完成的。
  • ·随着咱们使用Docker容器,构建,部署和启动微服务的速度将大大提升(比常规VM快得多)

Kubernetes经过容许将Linux容器集群做为一个系统进行管理,跨多个主机管理和运行Docker容器,提供容器的共置,服务发现和复制控制功能,扩展了Docker的功能。 如所见,大多数这些功能在咱们的微服务环境中也是必不可少的。 所以,使用Kubernetes(在Docker之上)进行微服务部署已成为一种极其强大的方法,尤为是对于大规模微服务部署。

将微服务构建和部署为容器。

在上图中,它显示了零售应用程序的微服务部署的概述。 每一个微服务实例都做为一个容器部署,每一个主机有两个容器。 你能够任意更改在给定主机上运行的容器的数量。

安全

在实际场景中使用微服务时,保护微服务是很是广泛的要求。 在进入微服务安全性以前,让咱们快速看一下咱们一般如何在总体应用程序级别上实现安全性。

  • 在典型的总体应用程序中,安全性是要找到“谁是呼叫者”,“呼叫者能作什么”和“咱们如何传播该信息”。
  • 这一般是在请求处理链的开始处的通用安全组件上实现的,而且该组件使用基础用户存储库(或用户存储)填充所需的信息。

那么,咱们能够直接将此模式转换为微服务架构吗? 是的,但这须要在每一个微服务级别实现的安全组件,该组件正在与集中式/共享用户存储库进行对话并检索所需的信息。 这是解决微服务安全性问题的很是乏味的方法。 相反,咱们能够利用普遍使用的API安全标准(例如OAuth2OpenID Connect)为咱们的微服务安全问题找到更好的解决方案。 在深刻探讨这一点以前,让我概述一下每一个标准的目的以及如何使用它们

  • ·OAuth2-是访问委派协议。 客户端经过受权服务器进行身份验证,并得到一个不透明的令牌,称为“访问令牌”。 访问令牌的用户/客户端信息为零。 它仅具备对只能由受权服务器检索的用户信息的引用。 所以,这被称为“参考令牌”,即便在公共网络/互联网中也能够安全地使用此令牌。

·OpenIDConnect的行为相似于OAuth,但除了访问令牌外,受权服务器还会发布一个ID令牌,其中包含有关用户的信息。 这一般由JWTJSON Web令牌)实现,并由受权服务器签名。 所以,这确保了受权服务器和客户端之间的信任。 所以,JWT令牌被称为“按值令牌”,由于它包含用户的信息,而且显然在内部网络以外使用它是不安全的。

具备OAuth2和OpenID Connect的微服务安全性

如上图所示,这些是实现微服务安全性涉及的关键步骤:

  • ·将身份验证留给OAuthOpenID Connect服务器(受权服务器),以便在有人有权使用数据的状况下,微服务成功提供访问权限。
  • ·使用API​​-GW样式,在该样式中,全部客户端请求都有一个入口点。
  • 客户端链接到受权服务器并得到访问令牌(按引用令牌)。而后将访问令牌与请求一块儿发送到API-GW
  • 网关上的令牌转换-API-GW提取访问令牌并将其发送到受权服务器以检索JWT(按值令牌)。
  • ·而后,GW将这个JWT与请求一块儿传递给微服务层。
  • ·JWT包含必要的信息,以帮助存储用户会话等。若是每一个服务均可以理解JSON Web令牌,则你已经分发了身份识别机制,该机制容许你在整个系统中传输身份。
  • 在每一个微服务层,咱们能够有一个处理JWT的组件,这是一个很是简单的实现。

交易次数

微服务中的交易支持如何?实际上,支持跨多个微服务的分布式事务是很是复杂的任务。微服务架构自己鼓励服务之间的无事务协调。

想法是,给定的服务是彻底独立的,而且基于单一责任原则。跨多个微服务进行分布式事务的需求一般是微服务体系结构中设计缺陷的征兆,一般能够经过重构微服务的范围来解决。可是,若是必须在多个服务之间分配事务,则能够经过在每一个微服务级别引入“补偿操做”来实现这种状况。关键思想是,给定的微服务基于单一职责原则,若是给定的微服务没法执行给定的操做,咱们能够认为这是整个微服务的失败。而后,必须经过调用这些微服务的相应补偿操做来撤消全部其余(上游)操做。

失败的设计

微服务架构引入了一组分散的服务,而且与单片设计相比,增长了在每一个服务级别出现故障的可能性。 给定的微服务可能会因为网络问题,基础资源的不可用等缘由而失败。不可用或无响应的微服务不该致使整个基于微服务的应用程序崩溃。 所以,微服务应该是容错的,可以在可能的状况下恢复,而且客户端必须妥善处理它。

另外,因为服务随时可能发生故障,所以可以快速检测(实时监视)故障并在可能的状况下自动恢复服务也很重要。

在微服务上下文中,有几种经常使用的模式来处理错误。context.

断路器

当你对微服务进行外部调用时,你须要为每次调用配置一个故障监视器组件,而且当故障达到某个阈值时,该组件将中止对该服务的任何进一步调用(使电路跳闸)。 在必定数量的请求处于打开状态(你能够配置)以后,将电路更改回关闭状态。

这种模式很是有用,可避免没必要要的资源消耗,因为超时而致使的请求延迟,而且还使咱们有机会监视系统(基于活动的开路状态)。

隔板

因为微服务应用程序包含微服务的数量,所以基于微服务的应用程序一部分的故障不该影响其他的应用程序。 隔板模式是关于隔离应用程序的不一样部分的,所以应用程序中服务的故障不会影响任何其余服务。

暂停

超时模式是一种机制,当你认为微服务不会响应时,它可让你中止等待微服务的响应。 你能够在此处配置但愿等待的时间间隔。

那么,咱们在哪里以及如何在微服务中使用这些模式? 在大多数状况下,这些模式中的大多数都适用于网关级别。 这意味着当微服务不可用或没有响应时,在网关级别,咱们能够决定是否使用断路器或超时模式将请求发送到微服务。 一样,在网关级别实现诸如隔板等模式也是很是重要的,由于它是全部客户端请求的单个入口点,所以赠与服务的失败不该影响其余微服务的调用。

另外,网关能够用做中心点,当经过网关调用每一个微服务时,咱们能够得到状态并监视每一个微服务。

微服务,企业集成,API管理等

咱们已经讨论了微服务架构的各类特征,以及如何在现代企业IT环境中实现它们。可是,咱们应该记住,微服务不是万能药。流行语概念的盲目适应将没法解决“实际”企业IT问题。正如在整个博客文章中所看到的那样,微服务具备不少优点,咱们应该加以利用。可是,咱们还必须记住,用微服务解决全部企业IT问题是不现实的。例如,微服务架构促进了消除ESB做为中央总线的发展,可是在现实世界中,有不少不基于微服务的现有应用程序/服务。所以,要与它们集成,咱们须要某种集成总线。所以,理想状况下,微服务和其余企业体系结构概念(例如集成)的混合方法将更为现实。我将在另外一篇博客文章中进一步讨论它们。

本文灵感源于优锐课java架构学习分享,但愿这使你对如何在企业中使用微服务有了更清晰的认识。

相关文章
相关标签/搜索