本文为博主自学笔记整理,内容来源于互联网,如有侵权,请联系删除。
个人笔记:https://github.com/dbses/TechNotes
微服务架构中,经常会遇到下面问题。
当系统中存在大量独立服务时,如何有效识别和管理这些服务的实例?这将成为一大挑战!分布式系统,一定要能够实时对这些服务实例进行治理。
服务数量所衍生的另一个问题,是服务调用之间的关系会变得混乱,客户端与各个服务之间也会存在较高的耦合度,分布式系统需要提供简洁而明确的入口供客户端访问。
分布式环境下的调用,与单体系统中的方法级调用不同。服务间的跨进程调用可能出现各种意想不到的问题,这就需要在服务访问出错时进行合理的容错处理。
一旦系统被拆分成多个独立服务,分布式系统就需要确保分散在每个服务中的配置信息,以及所有服务在开发、测试和生产等环境中的配置信息得到统一管理。
服务远程调用的另一个问题是调用链路可能会很长,需要对整个调用链路进行监控和跟踪,从而高效发现服务调用过程中的异常场景和性能问题。
针对以上问题,解决方案如下。
服务治理:为了有效管理分布式系统中存在的大量服务实例,微服务架构引入了服务发现和服务注册机制,使得服务实例的管理变得自动化、透明化。
API 网关:为了降低服务客户端与服务提供者之间的耦合度,更好地简化调用过程,微服务架构专门提供了一个 API 网关,用来优化面向客户端的 API 设计。
服务容错:为了解决服务访问出错问题,微服务架构中提供了服务隔离、服务熔断和服务回退等面向服务调用端的有效容错机制。
配置中心:为了更好地组织和管理散落在各个服务中的配置信息,微服务架构提供了一个配置中心来集中化管理。
链路跟踪:为了高效监控服务调用的健康状态以及全链路的数据流转,微服务架构提供了链路跟踪机制,来对各个服务之间的调用过程进行统一管理。
课程设计
基础篇(1~3):这部分介绍微服务架构的基本要素和技术体系。
实践篇(4~34):
微服务架构的提出者 Martin Fowler 在其文章Microservices中定义了包括服务组件化、去中心化、基础设施自动化在内的多个微服务架构特点。基于这些特点提炼出构建微服务架构三大要素,即业务建模、技术体系和研发过程。
微服务架构的第一要素:业务建模
对于领域的划分,业界主流的分类方法认为,系统中的各个子域可以分成核心子域、支撑子域和通用子域三种类型,其中系统中的核心业务属于核心子域,专注于业务某一方面的子域称为支撑子域,可以作为某种基础设施的功能可以归到通用子域。下图就是一个典型的领域划分示例,来自电商系统:
服务建模本质上是一个为了满足业务需求,并通过技术手段将这些业务需求转换为可实现服务的过程。我们可以把业务体系中的服务分成如下几种类型:基础服务、通用服务、定制服务和其他服务等。
微服务架构的第二要素:技术体系
本课程基于目前业界主流的微服务实现技术提炼了八大技术体系,包括服务通信、服务治理、服务路由、服务容错、服务网关、服务配置、服务安全和服务监控。
微服务架构而言,我们关注的是网络连接模式、I/O 模型和服务调用方式。
基于TCP 协议的网络连接有两种基本方式,也就是通常所说的长连接和短连接。
服务之间通信的另一个关注点是 I/O 模型。I/O 模型也有阻塞式 I/O 和非阻塞式 I/O 等多种实现方式。
服务通信的另一个主题是调用方式,这方面同样存在同步调用和异步调用两大类实现机制,这两大类机制对于开发人员使用开发框架的方式有很大影响。
当服务数量达到一定量级时,就需要引入独立的媒介来管理服务的实例,这个媒介一般被称为服务注册中心。
服务注册中心是保存服务调用所需的路由信息的存储仓库,也是服务提供者和服务消费者进行交互的媒介,充当着服务注册和发现服务器的作用。
当客户端请求到达集群,如何确定由哪一台服务器进行请求响应呢?这就是服务路由问题。
为实现精细化的路由管理,这时候我们就可以采用路由规则。路由规则常见的实现方案是白名单或黑名单,即把需要路由的服务地址信息(如服务 IP)放入可以控制是否可见的路由池中进行路由。同样,路由规则也是微服务开发框架的一项常见功能。
对于分布式环境中的服务而言,服务在自身失败引发生错误的同时,还会因为依赖其他服务而导致失败。除了比较容易想到和实现的超时、重试和异步解耦等手段之外,我们需要考虑针对各种场景的容错机制。
服务网关也叫 API 网关,封装了系统内部架构,为每个客户端提供一个定制的 API。在微服务架构中,服务网关的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。
在微服务架构中,考虑到服务数量和配置信息的分散性,一般都需要引入配置中心的设计思想和相关工具。与注册中心一样,配置中心也是微服务架构中的基础组件,其目的也是对服务进行统一管理,区别在于配置中心管理的对象是配置信息而不是服务的实例信息。
在对微服务架构的学习过程中,服务安全是一块非常重要但又容易被忽视的内容。一般意义上的访问安全性,都是围绕认证和授权这两个核心概念来展开的。也就是说我们首先需要确定用户身份,然后再确定这个用户是否有访问指定资源的权限。站在单个微服务的角度讲,我们系统每次服务访问都能与授权服务器进行集成以便获取访问 Token。站在多个服务交互的角度讲,我们需要确保 Token 在各个微服务之间的有效传播。另一方面,服务内部,我们可以使用不同的访问策略限制服务资源的访问。
在微服务架构中,当服务数量达到一定量级时,我们难免会遇到两个核心问题。一个是如何管理服务之间的调用关系?另一个是如何跟踪业务流的处理过程和结果?这就需要构建分布式服务跟踪机制。
微服务架构的第三要素:研发过程
当寻找把一个大的应用程序进行拆分的方法时,研发过程通常都会围绕产品团队、项目管理、大前端和服务器端团队而展开,这些团队也就是通常所说的职能团队。任何一个需求,无论大小,都将导致跨团队协作,从而增加沟通和协作成本。而微服务架构则倾向围绕业务功能的组织来分割服务,而不是面向某项技术能力。因此,团队是跨职能的特征团队,每个服务都围绕着业务进行构建,并且能够被独立部署到生产环境。
从 Spring Boot 到 Spring Cloud
Spring Boot 特性主要体现在开发过程的简单化,包括支持快速构建项目、不依赖外部容器独立运行、开发部署效率高,以及与云平台天然集成等。
在微服务架构中,Spring Cloud 构建在 Spring Boot 之上,继承了 Spring Boot 的多项功能特性,使得开发微服务变得简单而高效。
Spring Cloud 中的核心组件
Spring Cloud 中包含了开发一个完整的微服务系统所需的几乎所有技术组件,包括服务注册和发现、API 网关、配置中心、消息处理、负载均衡、熔断器、数据监控等。
在服务治理场景下,这些组件构成了一个完整的从服务注册、服务发现到服务调用的流程。
Spring Cloud Gateway 构建在最新版本的 Spring 5 和响应式编程框架 Project Reactor 之上,提供了非阻塞的 I/O 通信机制。
Spring Cloud Circuit Breaker 是对熔断器实现方案的一种抽象。在该组件的内部,Spring Cloud Circuit Breaker 集成了Netfix Hystrix、Resilience4J、Sentinel、Spring Retry这四种熔断器实现工具。
在 Spring Cloud 中,集中化配置中心服务器的实现依赖于 Spring Cloud Config,而配置仓库的实现方案除了本地文件系统之外,还支持Git、SVN等常见的版本控制工具。
Spring Cloud Stream 中的 Source 组件是真正生成消息的组件,然后消息通过 Channel 传送到 Binder。这里的 Binder 是一个中间层组件,通过 Binder 可以与特定的消息中间件进行通信。
在 Spring Cloud Stream 中,目前已经内置集成的消息中间件包括 RabbitMQ 和 Kafka。消息消费者则同样通过 Binder 从消息传递系统中获取消息,消息通过 Channel 将流转到 Sink 组件。
Spring Cloud Security 具备众多特点,包括基于流行的OAuth2 协议的授权机制,以及基于 Token的资源访问保护机制。
我们可以通过Spring Cloud Sleuth自动完成服务调用链路的构建。
任何通过 HTTP 端点接收到的请求或使用 RestTemplate 发出的请求都可以被 Spring Cloud Sleuth 自动收集日志。
同时它也能无缝支持通过由 API 网关 Zuul 发送的请求,以及基于 Spring Cloud Stream 等消息传递技术发送的请求。
并且,Spring Cloud Sleuth 也兼容了 Zipkin、HTrace 等第三方工具的应用和集成,从而实现对服务依赖关系、服务调用时序,以及服务调用数据的可视化,如下图所示。
在微服务架构中,当不同服务之间进行交互和集成时,测试的关注点就变成如何确保服务定义和协议级别的正确性和稳定性,也就是所谓的端到端测试。
Spring Cloud Contract 框架采用了服务桩(Stub) 实现机制来确保特定服务版本的各个服务之间交互过程的正确性,如下所示:
在物联网和智能穿戴式设备日益发达的当下,试想一下这样的日常场景。
患者通过智能手环、便携式脉诊仪等一些智能穿戴式设备检测自身的各项健康信息,然后把这些健康信息实时上报到云平台,云平台检测到用户健康信息中的异常情况时会通过人工或自动的方式进行一定的健康干预,从而确保用户健康得到保证。
这是大健康领域非常典型的一个业务场景,也是我们案例的来源。
SpringHealth:案例驱动
服务建模是案例分析的第一步。服务建模包括 子域与界限上下文的划分 以及 服务拆分和集成策略的确定。
SpringHealth 包含的业务场景比较简单,用户佩戴着各种穿戴式设备,云平台中的医护人员可以根据这些设备上报的健康信息生成健康干预。而在生成健康干预的过程中,我们需要对设备本身以及用户信息进行验证。从领域建模的角度进行分析,我们可以把该系统分成三个子域,即:
用户(User)子域,用于用户管理,用户可以通过注册成为系统用户,同时也可以修改或删除用户信息,并提供用户信息有效性验证的入口。
设备(Device)子域,用于设备管理,医护人员可以查询某个用户的某款穿戴式设备以便获取设备的详细信息,同时基于设备获取当前的健康信息。
健康干预(Intervention)子域,用于健康干预管理,医护人员可以根据用户当前的健康信息生成对应的健康干预。当然,也可以查询自己所提交健康干预的当前状态。
从子域的分类上讲,用户子域比较明确,显然应该作为一种通用子域。而健康干预是 SpringHealth 的核心业务,所以应该是核心子域。至于设备子域,在这里比较倾向于归为支撑子域。
基于以上分析,我们可以把 SpringHealth 划分成三个微服务,即 user-service、device-service 和 intervention-service。
以上述三个服务构成了 SpringHealth 的业务主体,属于业务微服务。
SpringHealth:服务设计
纵观整个 SpringHealth 系统,除了前面介绍的三个业务微服务之外,实际上更多的服务来自非业务性的基础设施类服务。
整个 SpringHealth 的所有服务如下表所示。对于基础设施类服务,命名上我们统一以 -server 来结尾,而对于业务服务,则使用的是 -service 后缀。
我们针对三个业务服务,建立独立的三个数据库,数据库的访问信息通过配置中心进行集中管理,如下图所示:
SpringHealth:代码工程
服务运行时上存在一定的依赖性。
案例之外:从案例实战到原理剖析
我们将通过源码解析来剖析 Spring Cloud 中核心组件的工作原理,典型的场景包括以下几点: