使用微服务架构最关键的一个原则就是将系统划分成一个个相互隔离、无依赖的微服务,这些微服务通过定义良好的协议进行通信。而响应式微服务架构,又有其独特的设计原则和理念。
在微服务架构中,我们经常会提到雪崩效应(Avalanche Effect)这一概念。服务雪崩的产生是一种扩散效应。当系统中存在两个服务A和B,如果A服务出现问题,而B服务会通过用户不断提交服务请求等手工重试或代码逻辑自动重试等手段进一步加大对A服务的访问流量。因为B服务使用同步调用,会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,B服务提供的服务本身也将处于不可用状态,整个过程的演变可参考下图。而这一效果在整个服务访问链路上进行扩散,就形成了雪崩效应。
雪崩效应示意图
雪崩效应的预防需要依赖于架构设计中的一种称为舱壁隔离(Bulkhead Isolation)的架构模式。所谓舱壁隔离,顾名思义就是像舱壁一样对资源或失败单元进行隔离,如果一个船舱破了进水,只损失一个船舱,其他船舱可以不受影响。舱壁隔离模式在微服务架构中的应用就是各种服务隔离思想。
隔离是微服务架构中最重要的特性,也是实现响应式宣言中所提倡的弹性、可伸缩系统的前提。所谓弹性,就是从失败中恢复的能力,依赖于这种舱壁和失败隔离的设计,并且需要打破同步通信机制。由此,微服务一般是在边界之间使用异步消息传输,从而使得正常的业务逻辑避免对捕获错误、错误处理的依赖。
上面所讲的隔离性是自主性的前提。只有当服务之间是完全隔离的,才可能实现完全的自主,包括独立的决策、独立的行动以及与其他服务协调合作来解决问题。
从实现上讲,服务自主性仅仅需要确保其对外公布协议的正确性即可。自主性不仅能够让我们更好地了解微服务系统以及各个服务的领域模型,也能够在面对冲突和失败状况时,确保快速定位到问题出在具体的哪一个微服务中。
大家都知道面向对象设计中有一条单一职责原则(Single Responsibility Principle,SRP),而在微服务架构中一个很大的问题是如何正确地划分各个服务的大小。多大的粒度才能被称之为“微”服务,显然,这个“微”是和服务本身的职责有直接关系,我们希望一个服务只做一件事,而且在服务内部要把相关的功能做到尽量好。
每一个服务都应该只有一个存在的原因,业务和职责不应该糅杂在一起。如果满足这个要求,所有的服务组织在一起从整体上就能够便于扩展、具有弹性、易理解和维护。
在软件设计领域经常会提到状态(State)这个词,而服务之间的状态本质上体现的还是一种数据关系。如果一个数据需要在多个服务之间共享才能完成一项业务功能,那么这项业务功能就被称为有状态。基于这项业务功能所设计和实现的一系列服务之间就形成了一种状态性,这一系列服务就是有状态服务。
很多服务都会把自己的状态下沉到一个庞大的共享数据库中,这也是一些传统Web框架的做法。这种做法就会造成在扩展性、可用性以及数据集成上很难做好把控。而在本质上,一个使用共享数据库的微服务架构本质还是一个单体应用。一个服务既然具有单一职责,那么合理的方式就应该是该服务拥有自己的状态和持久化机制,建模成一个边界上下文。这里就需要充分应用领域驱动设计(Domain Driven Design,DDD)中的相关策略设计和技术设计方面的方法和工程实践。关于领域驱动设计以及背后的Event Sourcing(事件溯源)和CQRS(Command Query Responsibility Segreation,命令查询职责分离)等概念,读者可参考《实现领域驱动设计》,这里不做具体展开。
从软件设计上讲存在三种不同层级的耦合度,即技术耦合、空间耦合和时间耦合。技术耦合度表现在服务提供者与服务消费者之间需要使用同一种技术实现方式。如下图a中服务提供者与服务消费者都使用RMI(Remote Method Invocation)作为通信的基本技术,而RMI是Java领域特有的技术,也就意味着其他服务消费者想要使用该服务也只能采用Java作为它的基本开发语言;空间耦合度指的是服务提供者与服务消费者都需要使用统一的方法签名才能相互协作,下图b中的getUserById(id)方法名称和参数的定义就是这种耦合的具体体现;而时间耦合度则表现在服务提供者与服务消费者只有同时在线才能完成一个完整的服务调用过程,如果出现下图c中所示的服务提供者不可用的情况,显然,服务消费者调用该服务就会发生失败。
耦合度的三种表现形式
微服务之间通信的最佳机制就是异步消息传递,消息传递能够从技术、空间和时间等多个维度上缓解甚至消除图1-6中的三种耦合度。我们在第5章中会进一步对该话题展开讨论。
同时,异步非阻塞执行是对资源的高效操作,能够最小化访问共享资源时的阻塞消耗,从而提升整体系统的性能。
异步消息传递带来了服务的位置透明性。所谓位置透明,指的是在多核或者多结点上的微服务在运行时无须改变结点,即可动态扩展的能力。这也决定了系统的弹性和移动性,要实现这些需要依赖云计算带来的一些特性和按需使用的模型。
另一方面,可寻址则是指服务的地址需要稳定,从而可以无限地引用此服务,无论服务目前是否可以被定位到。当服务在运行中、已停止、被挂起、升级中、已崩溃等情形下,地址都应该是可用的,任意客户端能够随时发送消息给一个地址。从这个角度讲,地址应该是虚拟的,可以代表一组实例提供的服务。使用虚拟地址能够让服务消费方无须关心服务目前是如何配置操作的,只要知道地址即可。
该书是这一技术领域唯一的书籍资料。也常被译作“反应式”的Reactive系统,诚然有其复杂性和挑战性,但需求持续增长已是不争事实。更重要的是,Spring最新版对其较为成熟的支持,让核心问题得以圆满解决,响应式和微服务从而实现历史性的会师。、
Spring响应式微服务
本书从响应式编程和微服务架构的基本概念开始展开,带领读者了解响应式的基本原理,以及Spring 5框架所集成的Project Reactor响应式开发框架。
本书还会进一步学习如何构建响应式RESTful服务、如何构建响应式数据访问组件、如何构建响应式消息通信组件、如何构建响应式微服务架构,以及如何测试响应式微服务架构等核心主题。所有这些内容都将应用于一个精简而又完整的示例项目,确保大家能够将所学到的技能付诸于实践。
完整目录请见本书
第1章 直面响应式微服务架构
1.1 响应式系统核心概念
1.2 剖析微服务架构
1.3 构建响应式微服务架构
1.4 全书架构
第2章 响应式编程模型与Reactor框架
2.1 响应式编程模型
2.2 Reactor框架
2.3 创建Flux和Mono
2.4 Flux和Mono操作符
2.5 Reactor框架中的背压机制
第3章 构建响应式RESTful服务
3.1 使用Spring Boot 2.0构建微服务
3.2 使用Spring WebFlux构建响应式服务
第4章 构建响应式数据访问组件
4.1 Spring Data数据访问模型
4.2 响应式数据访问模型
4.3 响应式Mongodb
4.4 响应式Redis
第5章 构建响应式消息通信组件
5.1 消息通信系统简介
5.2 使用Spring Cloud Stream构建消息通信系统
5.3 引入Reactive Spring Cloud Stream实现响应式 消息通信系统
第6章 构建响应式微服务架构
6.1 使用Spring Cloud创建响应式微服务架构
6.2 使用WebClient实现响应式服务调用
第7章 测试响应式微服务架构
7.1 初始化测试环境
7.2 测试Reactor组件
7.3 测试响应式Repository层组件
7.4 测试响应式Service层组件
7.5 测试响应式Controller层组件
第8章 响应式微服务架构演进案例分析
8.1 PrescriptionSystem案例简介
8.2 传统微服务架构实现案例
8.3 响应式微服务架构演进案例
留言与评论(共有 0 条评论) |