开发客户端 - 服务器应用程序的重点是建立在每个层中使用特定技术的分层应用程序。这样的应用通常被称为单片应用,并且被封装在用于峰值负载预分配的硬件上。这种开发方法的主要缺点是每个层级组件之间的紧密耦合,各个组件不能轻易缩放,并且测试成本。一个简单的更新可能对该层的其余部分产生不可预见的影响,因此更改应用程序组件需要对其整个层进行重新测试并重新部署。
特别是在云时代,个别组件不能轻松扩展。单片应用程序包含域特定的功能,通常由前端,业务逻辑和数据存储等功能层划分。通过将整个应用程序克隆到多台机器上来整合单片应用程序,如图8-1所示。
图8-1:单片应用程序缩放方法
微服务
微服务提供了不同的应用程序开发和部署方法,这种方法适合现代云应用的敏捷性,规模和可靠性要求。微服务应用程序被分解成独立的组件,它们一起工作以提供应用程序的整体功能。微服务术语强调,应用程序应由足够小的服务组成,以反映独立的关注点,以便每个微服务器实现单个功能。此外,每个微服务都具有明确的合同,以便其他微服务器可以与其进行通信和共享数据。微服务的典型例子包括购物车,库存处理,采购子系统和支付处理。
相比之下,微型服务可以独立扩展,而不是大规模集成应用。这意味着需要更多处理能力或网络带宽来支持需求的特定功能区域可以被缩放而不是不必要地缩小应用程序的其他区域。图8-2说明了这种方法,其中微服务部署和独立扩展,创建跨机器服务的实例。
图8-2:微服务应用程序缩放方法
微服务横向扩展可以几乎瞬时,允许应用程序适应变化的负载。例如,应用程序面向Web的功能中的单个微服务器可能是应用程序中唯一需要扩展以处理其他传入流量的微服务器。
应用程序可扩展性的经典模型是具有负载均衡的无状态层,其中包含共享外部数据存储以存储持久数据。有状态的微服务管理自己的持久性数据,通常将其存储在其所在的服务器上,以避免网络访问的开销和跨服务操作的复杂性。这样可以最快地处理数据,并可以消除对缓存系统的需求。此外,可扩展的状态微服务通常在其实例之间分配数据,以便管理数据大小和传输吞吐量,超过单个服务器可以支持的数据量。
Microservices还支持独立更新。微服务之间的松散耦合提供了快速可靠的应用演进。它们独立的分布式特性支持滚动更新,只有一个微服务器的实例的一个子集在任何给定的时间才能更新。因此,如果检测到问题,则可以在所有实例使用故障代码或配置进行更新之前回滚错误更新。类似地,微服务通常使用模式版本控制,以便客户端在应用更新时看到一致的版本,无论与哪个微服务器实例进行通信。
因此,微服务应用程序与单片应用程序有很多好处:
· 每个微服务器相对较小,易于管理和演进。
· 可以独立于其他服务开发和部署每个微服务器。
· 每个微服务都可以独立扩展。例如,目录服务或购物篮服务可能需要比订购服务进行扩展。因此,所产生的基础架构将在扩展时更有效地消耗资源。
· 每个微服务器隔离任何问题。例如,如果服务中存在问题,则仅影响该服务。其他服务可以继续处理请求。
· 每个微服务器都可以使用最新的技术。由于微服务是自主的,并行运行,所以可以使用最新的技术和框架,而不是被迫使用可能被单片应用程序使用的旧框架。
然而,基于微服务的解决方案也有潜在的缺点:
· 选择如何将应用程序分割成微服务器可能具有挑战性,因为每个微服务器必须是完全自主的,端到端的,包括对其数据源的责任。
· 开发人员必须实施业务间通信,这增加了应用程序的复杂性和延迟。
· 多个微服务器之间的原子交易通常是不可能的。因此,业务需求必须包含微服务之间的最终一致性。
· 在生产中,部署和管理许多独立服务受损害的系统存在操作复杂性。
· 直接的客户端与微服务器的通信可能难以重构微服务的合同。例如,随着时间的推移,系统如何划分为服务可能需要改变。单个服务可能会分为两个或更多服务,两个服务可能会合并。当客户端直接与微服务器通信时,此重构工作可能会破坏与客户端应用的兼容性。
容器化
容器化是软件开发的一种方法,其中将应用程序及其版本化依赖关系集以及其环境配置抽象为部署清单文件,作为容器映像打包在一起,作为一个单元进行测试,并部署到主机操作系统。
容器是一个独立的资源控制和便携式操作环境,应用程序可以在不触及其他容器或主机的资源的情况下运行。 因此,容器看起来像新安装的物理计算机或虚拟机。
容器和虚拟机之间有很多相似之处,如图8-3所示。
图8-3:虚拟机和容器的比较
容器运行操作系统,具有文件系统,并且可以通过网络访问,就像它是物理机或虚拟机一样。然而,容器使用的技术和概念与虚拟机非常不同。虚拟机包括应用程序,所需的依赖关系以及完整的客户机操作系统。容器包括应用程序及其依赖关系,但与其他容器共享操作系统,作为主机操作系统上的隔离进程运行(除了每个容器的专用虚拟机内运行的Hyper-V容器之外)。因此,容器共享资源,并且通常比虚拟机需要更少的资源。
面向容器的开发和部署方法的优点在于它消除了环境设置不一致以及与之相关的问题所产生的大多数问题。此外,容器允许通过根据需要实施新的容器来快速应用放大功能。
创建和使用容器时的关键概念是:
· 容器主机:配置为托管容器的物理或虚拟机。容器主机将运行一个或多个容器。
· 容器镜像:图像由堆叠在一起的分层文件系统的联合组成,并且是容器的基础。镜像没有状态,它不会随着部署到不同的环境而改变。
· 容器:容器是图像的运行时实例。
· 容器操作系统映像:从映像部署容器。容器操作系统映像是构成容器的潜在许多图像层中的第一层。容器操作系统是不可变的,不能修改。
· 容器存储库:每次创建容器映像时,映像及其依赖项都存储在本地存储库中。这些图像可以在容器主机上重复使用多次。容器映像也可以存储在公共或私有注册表(如)中,以便它们可以在不同容器主机之间使用。
企业在实施基于微服务的应用程序时越来越多地采用容器,而Docker已经成为大多数软件平台和云供应商采用的标准容器实现。
eShopOnContainers参考应用程序使用Docker来托管四个容器式后端微服务器,如图8-4所示。
图8-4:eShopOnContainers参考应用后端微服务
参考应用程序中后端服务的体系结构以协作微服务和容器的形式分解为多个自主子系统。 每个微服务提供单一功能区域:身份服务,目录服务,订购服务和篮子服务。
每个微服务器都有自己的数据库,允许它与其他微服务器完全分离。 必要时,使用应用程序级事件实现来自不同微服务器的数据库之间的一致性。 有关更多信息,请参阅。
有关参考应用程序的更多信息,请参阅。
客户与微服务之间的通信
eShopOnContainers移动应用程序使用直接的客户端到微服务器通信与容器化的后端微服务进行通信,如图8-5所示。
图8-5:直接的客户端到微服务器通信
通过直接的客户端到微服务器通信,移动应用程序通过其公共端点直接向每个微服务器发出请求,每个微服务器具有不同的TCP端口。 在生产中,端点通常映射到微服务器的负载均衡器,该平衡器在可用实例之间分配请求。
? 提示:考虑使用API网关通信。 当构建基于大型和复杂的基于微服务的应用程序时,直接的客户端到微服务器通信可能具有缺点,但是对于小型应用程序来说,这是足够的。 当设计具有数十个微服务器的大型基于微服务的应用程序时,请考虑使用API网关通信。 有关更多信息,请参阅。
微服务之间的通信
基于微服务的应用程序是分布式系统,可能运行在多台机器上。每个服务实例通常是一个进程。因此,服务必须使用诸如HTTP,TCP,高级消息队列协议(AMQP)或二进制协议之类的进程间通信协议进行交互,这取决于每个服务的性质。
微服务到微服务通信的两种常见方法是在查询数据时进行基于HTTP的REST通信,以及在跨多个微服务器通信更新时的轻量级异步消息传递。
当跨多个微服务传播更改时,基于异步消息传递的事件驱动通信至关重要。通过这种方法,当一个值得注意的事件发生时,一个微服务器发布一个事件,例如当它更新一个业务实体时。其他微服务订阅这些事件。然后,当微服务器收到一个事件时,它会更新自己的业务实体,这可能会导致更多的事件被发布。这种发布订阅功能通常通过事件总线实现。
事件总线允许微服务之间的发布 - 订阅通信,而不需要组件彼此明确地识别,如图8-6所示。
图8-6:发布订阅事件总线
从应用的角度来看,事件总线只是一个通过接口公开的发布订阅通道。 然而,事件总线的实现方式可能会有所不同。 例如,事件总线实现可以使用RabbitMQ,Azure服务总线或其他服务总线,如NServiceBus和MassTransit。 图8-7显示了eShopOnContainers参考应用程序中事件总线的使用方法。
图8-7:参考应用中的异步事件驱动通信
使用RabbitMQ实现的eShopOnContainers事件总线提供一对多异步发布订阅功能。 这意味着在发布事件之后,可以有多个订阅者监听相同的事件。 图8-9说明了这种关系。
图8-9:一对多通信
这种一对多通信方法使用事件来实现跨越多个服务的业务事务,确保服务之间的最终一致性。 最终一致的事务由一系列分布式步骤组成。 因此,当用户简档微服务器接收到UpdateUser命令时,它会更新用户在其数据库中的详细信息,并将UserUpdated事件发布到事件总线。 篮子微服务器和订购微服务器已订阅接收该事件,并且响应于在其各自的数据库中更新其买方信息。
注意:使用RabbitMQ实现的eShopOnContainers事件总线仅用作概念证明。 对于生产系统,应考虑替代事件总线实现。
有关事件总线实现的信息,请参阅。
概要
微服务提供了适用于现代云应用的敏捷性,规模和可靠性要求的应用程序开发和部署方法。 微服务的主要优点之一是可以独立扩展,这意味着可以对特定的功能区进行扩展,这需要更多的处理能力或网络带宽来支持需求,而不会不必要地缩放没有经历的应用程序区域 需求增加。
容器是一个独立的资源控制和便携式操作环境,应用程序可以在不触及其他容器或主机的资源的情况下运行。 企业在实施基于微服务的应用程序时越来越多地采用容器,而Docker已经成为大多数软件平台和云供应商采用的标准容器实现。